代码之家  ›  专栏  ›  技术社区  ›  Kurt

枚举或列出[此处为您喜爱的语言][已关闭]程序中的所有变量

  •  74
  • Kurt  · 技术社区  · 17 年前

    上周,一位朋友问我如何枚举或列出程序/函数/等中的所有变量,以便进行调试(基本上是获取所有变量的快照,以便您可以查看设置了哪些变量,或者是否设置了这些变量)。我环顾四周,找到了一种比较好的Python方法:

    #!/usr/bin/python                                                                                                                                                                                                                           
    foo1 = "Hello world"
    foo2 = "bar"
    foo3 = {"1":"a",
            "2":"b"}
    foo4 = "1+1"
    
    for name in dir():
        myvalue = eval(name)
        print name, "is", type(name), "and is equal to ", myvalue
    

    __builtins__ is <type 'str'> and is equal to  <module '__builtin__' (built-in)>
    __doc__ is <type 'str'> and is equal to  None
    __file__ is <type 'str'> and is equal to  ./foo.py
    __name__ is <type 'str'> and is equal to  __main__
    foo1 is <type 'str'> and is equal to  Hello world
    foo2 is <type 'str'> and is equal to  bar
    foo3 is <type 'str'> and is equal to  {'1': 'a', '2': 'b'}
    foo4 is <type 'str'> and is equal to  1+1
    

    到目前为止,我已经在PHP中找到了部分方法(由 link text )但它只列出了所有变量及其类型,而没有列出内容:

    <?php
    // create a few variables
    $bar = 'foo';
    $foo ='bar';
    // create a new array object
    $arrayObj = new ArrayObject(get_defined_vars());
    // loop over the array object and echo variables and values
    for($iterator = $arrayObj->getIterator(); $iterator->valid(); $iterator->next())
            {
            echo $iterator->key() . ' => ' . $iterator->current() . '<br />';
            }
    ?>
    


    编辑人 VonC 当前位置我提出这一问题符合“一点”的精神 code-challenge ".
    如果您不同意,只需编辑并删除标记和链接。

    16 回复  |  直到 9 年前
        1
  •  96
  •   Aaron Maenpaa    17 年前

    在python中,使用局部变量返回包含所有局部绑定的字典,从而避免了eval:

    >>> foo1 = "Hello world"
    >>> foo2 = "bar"
    >>> foo3 = {"1":"a",
    ...         "2":"b"}
    >>> foo4 = "1+1"
    
    >>> import pprint
    >>> pprint.pprint(locals())
    {'__builtins__': <module '__builtin__' (built-in)>,
     '__doc__': None,
     '__name__': '__main__',
     'foo1': 'Hello world',
     'foo2': 'bar',
     'foo3': {'1': 'a', '2': 'b'},
     'foo4': '1+1',
     'pprint': <module 'pprint' from '/usr/lib/python2.5/pprint.pyc'>}
    
        2
  •  13
  •   Eder Santana    13 年前

    伊皮顿:

    whos

    你也可以推荐 Spyder 给你的朋友,它像Matlab一样显示这些变量,并为逐行调试提供GUI。

        3
  •  11
  •   Jörg W Mittag    10 年前

    这就是它在中的样子 Ruby :

    #!/usr/bin/env ruby
    
    foo1 = 'Hello world'
    foo2 = 'bar'
    foo3 = { '1' => 'a', '2' => 'b' }
    foo4 = '1+1'
    
    b = binding
    local_variables.each do |var|
      puts "#{var} is #{var.class} and is equal to #{b.local_variable_get(var).inspect}"
    end
    

    foo1 is String and is equal to "Hello world"
    foo2 is String and is equal to "bar"
    foo3 is String and is equal to {"1"=>"a", "2"=>"b"}
    foo4 is String and is equal to "1+1"

    foo3 应该是 Hash (或 dict String

    #!/usr/bin/env ruby
    
    foo1 = 'Hello world'
    foo2 = 'bar'
    foo3 = { '1' => 'a', '2' => 'b' }
    foo4 = '1+1'
    
    b = binding
    local_variables.each do |var|
      val = b.local_variable_get(var)
      puts "#{var} is #{val.class} and is equal to #{val.inspect}"
    end
    

    foo1 is String and is equal to "Hello world"
    foo2 is String and is equal to "bar"
    foo3 is Hash and is equal to {"1"=>"a", "2"=>"b"}
    foo4 is String and is equal to "1+1"
        4
  •  9
  •   Pim Jager    17 年前

    在php中,您可以执行以下操作:

    $defined = get_defined_vars(); 
    foreach($defined as $varName => $varValue){
     echo "$varName is of type ".gettype($varValue)." and has value $varValue <br>";
    }
    
        5
  •  9
  •   Nick Dandoulakis    17 年前

    for k,v in pairs(_G) do
      print(k..' is '..type(v)..' and is equal to '..tostring(v))
    end
    
        6
  •  6
  •   too much php    17 年前

    猛击:

    set
    

    免责声明:不是我最喜欢的语言!

        7
  •  6
  •   LapTop006    17 年前

    完全递归的PHP一行程序:

    print_r(get_defined_vars());
    
        8
  •  5
  •   Tiago Zortea    13 年前

    用R语言

    ls()
    

    并从工作记忆中删除所有对象

    rm(list=ls(all=TRUE))
    
        9
  •  4
  •   Marc Gravell    17 年前

    首先,我只需要使用调试器-P 例如,VisualStudio有“局部变量”和“监视”窗口,可以显示您想要的所有变量等,可以完全扩展到任何级别。

    在C#中,您无法很容易地获取方法变量(编译器很可能会删除它们),但您可以通过反射访问字段等:

    static class Program { // formatted for minimal vertical space
        static object foo1 = "Hello world", foo2 = "bar",
                      foo3 = new[] { 1, 2, 3 }, foo4;
        static void Main() {
            foreach (var field in typeof(Program).GetFields(
                    BindingFlags.Static | BindingFlags.NonPublic)) {
                var val = field.GetValue(null);
                if (val == null) {
                    Console.WriteLine("{0} is null", field.Name);
                } else {
                    Console.WriteLine("{0} ({1}) = {2}",
                        field.Name, val.GetType().Name, val);
                }
            }
        }
    }
    
        10
  •  4
  •   ephemient    17 年前

    Perl。无法处理 my

    my %env = %{__PACKAGE__ . '::'};
    while (($a, $b) = each %env) {
        print "\$$a = $$b\n";
        print "\@$a = (@$b)\n";
        print "%$a = (@{[%$b]})\n";
        print "*$a = $b\n";
    }
    
        11
  •  4
  •   Dario    17 年前

    Matlab:

    who
    
        12
  •  2
  •   Community Mohan Dere    9 年前

    在java中,问题类似于C#,只是在更详细的模式下(我知道, I KNOW you made that clear already ;) )

    可以通过Refection访问对象字段,但可能无法轻松访问方法局部变量。因此,以下内容不适用于静态分析代码,而仅适用于运行时调试。

    package test;
    
    import java.lang.reflect.Field;
    import java.security.AccessController;
    import java.security.PrivilegedAction;
    
    /**
     * 
     * @author <a href="https://stackoverflow.com/users/6309/vonc">VonC</a>
     */
    public class DisplayVars
    {
    
        private static int field1 = 1;
        private static String field2 = "~2~";
        private boolean isField = false;
    
        /**
         * @param args
         */
        public static void main(final String[] args)
        {
            final Field[] someFields = DisplayVars.class.getDeclaredFields();
            try
            {
                displayFields(someFields);
            } catch (IllegalAccessException e)
            {
                e.printStackTrace();
            }
        }
    
        /**
         * @param someFields
         * @throws IllegalAccessException
         * @throws IllegalArgumentException
         */
        @SuppressWarnings("unchecked")
        public static void displayFields(final Field[] someFields)
                throws IllegalAccessException
        {
            DisplayVars anObject = new DisplayVars();
            Object res = null;
            for (int ifields = 0; ifields < someFields.length; ifields++)
            {
                final Field aField = someFields[ifields];
                AccessController.doPrivileged(new PrivilegedAction() {
                    public Object run()
                    {
                        aField.setAccessible(true);
                        return null; // nothing to return
                    }
                });
                res = aField.get(anObject);
                if (res != null)
                {
                    System.out.println(aField.getName() + ": " + res.toString());
                } else
                {
                    System.out.println(aField.getName() + ": null");
                }
            }
        }
    }
    
        13
  •  1
  •   Gregory Higley    17 年前

    在REBOL中,所有变量都位于 上下文 object! . 有一个全局上下文,每个函数都有自己的隐式局部上下文。您可以通过创建新上下文来显式创建新上下文 对象 (或使用 context 功能)。这与传统语言不同,因为变量(在REBOL中称为“单词”)携带对其上下文的引用,即使它们已经离开了定义它们的“范围”。

    所以,底线是,给定一个上下文,我们可以列出它定义的变量。我们会用拉迪斯拉夫·梅西尔的 context-words? 作用

    context-words?: func [ ctx [object!] ] [ bind first ctx ctx ]
    

    现在我们可以列出在全局上下文中定义的所有单词。(有一个 (他们中的一个。)

    probe context-words? system/words
    

    我们还可以编写一个函数,然后列出它定义的变量。

    enumerable: func [a b c /local x y z] [
      probe context-words? bind? 'a
    ]
    

    我们 不能

        14
  •  1
  •   gregers    17 年前

    如果您安装了FireBug(或另一个带有console.log的浏览器),则可以使用快速且肮脏的JavaScript解决方案。如果不这样做,则必须将console.log更改为document.write,并在结束时以内联脚本的形式在处运行。将MAX_DEPTH更改为所需的递归级别(小心!)。

    (function() {
        var MAX_DEPTH = 0;
        function printObj(name, o, depth) {
            console.log(name + " type: '"+typeof o+"' value: " + o);
    
            if(typeof o == "function" || depth >= MAX_DEPTH) return;
            for(var c in o) {
                printObj(name+"."+c, o[c], depth+1);
            }
        }
        for(var o in window) {
            printObj(o, window[o], 0);
        }
    })();
    
        15
  •  0
  •   Svante    17 年前

    公共Lisp:

    (do-all-symbols (x) (print x))
    

    (do-all-symbols (x) (print x) (when (boundp x) (print (symbol-value x))))
    

    这是一个很长的列表,并不是特别有用。我真的会使用集成调试器。

        16
  •  0
  •   Tobias Langner    17 年前

    首先,您需要Java中的toString()之类的东西来打印有意义的内容。 第二,您必须将自己限制为一个对象层次结构。在根对象的构造函数中(与Eiffel中的任何构造函数一样),在创建时在某种全局列表中注册实例。在销毁过程中,取消注册(请确保使用一些允许快速插入/搜索/删除的数据结构)。在程序执行期间的任何时候,您都可以遍历此数据结构并打印在其中注册的所有对象。

    由于它的结构,埃菲尔铁塔可能非常适合这个用途。其他语言对于非用户定义的对象(例如jdk类)存在问题。在Java中,可以使用一些开源jdk创建自己的对象类。