枚举或列出的程序中的所有variables

上个星期朋友问我如何枚举或列出一个程序/函数等内的所有variables。 为了debugging的目的(基本上得到一切的快照,所以你可以看到什么variables设置,或者如果他们设置的话)。 我环顾了一下,发现了一个比较好的Python方法:

 #!的/ usr / bin中/python                                                                                                                                                                                                                           
 foo1 =“你好世界”
 foo2 =“bar”
 foo3 = {“1”:“a”,
         “2”: “B”}
 foo4 =“1 + 1”

对于dir()中的名称:
     myvalue = eval(name)
    打印名称,“是”,键入(名称),“等于”,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中find了部分方法(礼貌的链接文本 ),但它只列出了所有variables及其types,而不是内容:

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

所以我把它给你:你如何列出所有variables和他们的内容在你最喜欢的语言?


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

在python中,使用返回一个包含所有本地绑定的字典的局部variables,从而避免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'>} 

这就是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是String并且等于“Hello world”
 foo2是String并且等于“bar”
 foo3是string,等于{“1”=>“a”,“2”=>“b”}
 foo4是string,等于“1 + 1” 

但是,是不是要输出variables引用的对象types而不是用来表示variables标识符的types呢? IOW, foo3的types应该是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是String并且等于“Hello world”
 foo2是String并且等于“bar”
 foo3是散列,等于{“1”=>“a”,“2”=>“b”}
 foo4是string,等于“1 + 1” 

在PHP中,你可以这样做:

 $defined = get_defined_vars(); foreach($defined as $varName => $varValue){ echo "$varName is of type ".gettype($varValue)." and has value $varValue <br>"; } 

在Lua中,基本的数据结构就是表格 ,甚至全球环境_G就是一个表格。 所以,一个简单的枚举就可以做到这一点。

 for k,v in pairs(_G) do print(k..' is '..type(v)..' and is equal to '..tostring(v)) end 

击:

 set 

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

一个完全recursion的PHP单行:

 print_r(get_defined_vars()); 

首先,我只是简单地使用一个debugging器;例如,Visual Studio就有“Locals”和“Watch”窗口,它们将显示所有你想要的variables,完全可以扩展到任何级别。

在C#中,不能非常容易地获取方法variables(而且很多方法很容易被编译器删除),但是您可以通过reflection来访问字段等:

 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); } } } } 

Matlab的:

 who 

IPython的:

 whos 

你也可以推荐Spyder给你的朋友,它可以像Matlab那样显示那些variables,并提供一个用于逐行debugging的GUI。

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"; } 

在Java中,问题将类似于C#,只是在一个更详细的模式(我知道, 我知道 ;)Java是冗长的… 你已经明确已经;) )

您可以通过Refection访问对象字段,但是您可能无法轻松访问方法局部variables。 所以以下不是针对静态分析代码,而是针对运行时debugging。

 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"); } } } } 

在REBOL中,所有variables都存在于object!types的上下文object! 。 有一个全球背景,每个function都有其自己的隐含的本地背景。 您可以通过创build一个新object!显式创build新的上下文object! (或使用contextfunction)。 这与传统语言不同,因为variables(在REBOL中称为“单词”)提及了它们的上下文,即使它们已经离开了它们所定义的“范围”。

所以,底线是,给定一个上下文,我们可以列出它定义的variables。 我们将使用Ladislav Mecir的context-words? function。

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

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

 probe context-words? system/words 

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

 enumerable: func [abc /local xyz] [ probe context-words? bind? 'a ] 

据我所知,在REBOL中,我们无法做到的是在上下文树上行走,尽pipe解释者在决定如何将单词绑定到上下文时似乎能够很好地做到这一点。 我认为这是因为上下文树(即范围)在一个单词被绑定的时候可能有一个“形状”,但是在被评估的时候可能有另一个“形状”。

如果您安装了FireBug(或其他带有console.log的浏览器),则可以使用JavaScript解决scheme。 如果你不这样做,你将不得不把console.log改为document.write,然后在你的最后以一个内联脚本运行。 将MAX_DEPTH更改为您想要的recursion级别(请小心!)。

 (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); } })(); 

在R语言

 ls() 

并从工作内存中删除所有对象

 rm(list=ls(all=TRUE)) 

Common Lisp:

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

还要显示所有的绑定值:

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

这是一个很长的名单,并不是特别有用。 我真的会使用集成的debugging器。

这是一个关于oo语言的想法。

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

由于它的结构,埃菲尔可能是非常好的这个目的。 其他语言与用户定义的对象(如jdk类)有问题。 在Java中,使用某些开源jdk可能会创build自己的Object-class。