80

上周一位朋友问我如何枚举或列出程序/函数/等中的所有变量。出于调试的目的(基本上是获取所有内容的快照,以便您可以查看设置了哪些变量,或者是否设置了它们)。我环顾四周,发现了一个相对较好的 Python 方法:

#!/usr/bin/python                                                                                                                                                                                                                           
foo1 = "你好世界"
foo2 = "酒吧"
foo3 = {"1":"a",
        "2":"b"}
foo4 = "1+1"

对于 dir() 中的名称:
    我的价值 = 评估(名称)
    print name, "is", type(name), "and is equal to ", myvalue

这将输出如下内容:

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

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

<?php
// 创建一些变量
$bar = 'foo';
$foo ='酒吧';
// 创建一个新的数组对象
$arrayObj = new ArrayObject(get_defined_vars());
// 遍历数组对象并回显变量和值
for($iterator = $arrayObj->getIterator(); $iterator->valid(); $iterator->next())
        {
        回声 $iterator->key() 。' => ' 。$iterator->current() 。'<br />';
        }
?>

所以我告诉你:你如何用你最喜欢的语言列出所有变量及其内容?


VonC编辑:我建议这个问题遵循一点“代码挑战”的精神。
如果您不同意,只需编辑并删除标签和链接。

4

16 回答 16

98

在 python 中,使用返回包含所有本地绑定的字典的 locals,从而避免 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'>}
于 2009-01-10T11:30:39.630 回答
13

IPython:

whos

您还可以向您的朋友推荐Spyder,它非常像 Matlab 那样显示这些变量,并提供用于逐行调试的 GUI。

于 2013-06-06T21:29:37.410 回答
11

这就是它在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 是字符串,等于“Hello world”
foo2 是字符串,等于 "bar"
foo3 是字符串,等于 {"1"=>​​"a", "2"=>"b"}
foo4 是字符串,等于“1+1”

但是,您不是要输出变量引用的对象类型,而不是用于表示变量标识符的类型吗?IOW,的类型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 是字符串,等于“Hello world”
foo2 是字符串,等于 "bar"
foo3 是哈希,等于 {"1"=>​​"a", "2"=>"b"}
foo4 是字符串,等于“1+1”
于 2009-01-10T11:10:17.380 回答
9

在 php 中你可以这样做:

$defined = get_defined_vars(); 
foreach($defined as $varName => $varValue){
 echo "$varName is of type ".gettype($varValue)." and has value $varValue <br>";
}
于 2009-01-10T13:17:46.887 回答
9

在 Lua 中,基本的数据结构是,甚至全局环境 _G 也是表。因此,一个简单的枚举就可以解决问题。

for k,v in pairs(_G) do
  print(k..' is '..type(v)..' and is equal to '..tostring(v))
end
于 2009-05-23T18:28:11.923 回答
6

重击:

set

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

于 2009-05-26T03:33:42.337 回答
6

一个完全递归的 PHP 单行:

print_r(get_defined_vars());
于 2009-05-26T11:24:21.777 回答
5

在 R 语言中

ls()

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

rm(list=ls(all=TRUE))
于 2013-03-06T20:28:52.623 回答
4

首先,我只需使用调试器;-p Visual Studio,例如,具有“Locals”和“Watch”窗口,它们将显示您想要的所有变量等,完全可以扩展到任何级别。

在 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);
            }
        }
    }
}
于 2009-01-10T10:03:01.820 回答
4

珀尔。不处理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";
}
于 2009-03-19T16:42:59.340 回答
4

MATLAB:

who
于 2009-05-23T18:49:02.870 回答
2

在java中,问题类似于C#,只是在更详细的模式下(我知道,我知道;)Java很冗长......你已经说清楚了;)

您可以通过 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");
            }
        }
    }
}
于 2009-01-10T13:23:07.703 回答
1

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

所以,底线是,给定一个上下文,我们可以列出它定义的变量。我们将使用 Ladislav Mecir 的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
]

据我所知,我们在 REBOL中不能做的是沿着上下文树向上走,尽管解释器在决定如何将单词绑定到其上下文时似乎能够很好地做到这一点。我认为这是因为上下文树(即范围)在绑定单词时可能具有一个“形状”,但在评估时却完全不同。

于 2009-05-26T08:54:01.410 回答
1

如果您安装了 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);
    }
})();
于 2009-05-26T20:12:40.837 回答
0

普通 Lisp:

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

要同时显示所有绑定值:

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

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

于 2009-05-23T18:55:52.810 回答
0

这是 oo 语言的一个想法。

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

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

于 2009-05-25T16:19:26.227 回答