Enumerate or list all variables in a program of [y

2019-01-03 01:20发布

A friend asked me last week how to enumerate or list all variables within a program/function/etc. for the purposes of debugging (essentially getting a snapshot of everything so you can see what variables are set to, or if they are set at all). I looked around a bit and found a relatively good way for 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

which will output something like:

__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

I have so far found a partial way in PHP (courtesy of link text) but it only lists all variables and their types, not the contents:

<?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 />';
        }
?>

So I put it to you: how do you list all variables and their contents in your favorite language?


Edit by VonC: I propose this question follows the spirit of a little "code-challenge".
If you do not agree, just edit and remove the tag and the link.

16条回答
爷的心禁止访问
2楼-- · 2019-01-03 01:37

First, I'd simply use a debugger ;-p Visual Studio, for example, has "Locals" and "Watch" windows that will show all the variables etc you want, fully expandable to any level.

In C# you can't really get at method variables very easily (and they many well be removed by the compiler) - but you can access fields etc via 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);
            }
        }
    }
}
查看更多
兄弟一词,经得起流年.
3楼-- · 2019-01-03 01:38

Common Lisp:

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

To also show all bound values:

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

This is a long list, and not particularly useful. I would really use the integrated debugger.

查看更多
劫难
4楼-- · 2019-01-03 01:40

This is what it would look like in 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

which will output

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"

However, didn't you mean to output the type of object the variable references instead of the type used to represent the variable identifier? IOW, the type of foo3 should be Hash (or dict) instead of String, right? In that case, the code would be

#!/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

and the result is

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"
查看更多
Evening l夕情丶
5楼-- · 2019-01-03 01:43

In Lua the fundamental data structure is the table and even the global environment _G is a table. So, a simple enumeration will do the trick.

for k,v in pairs(_G) do
  print(k..' is '..type(v)..' and is equal to '..tostring(v))
end
查看更多
beautiful°
6楼-- · 2019-01-03 01:46

In REBOL, all variables live inside a context of type object!. There's a global context, and every function has its own implicit local context. You can create new contexts explicitly by creating a new object! (or using the context function). This is different from traditional languages because variables (called "words" in REBOL) carry a reference to their context around with them, even when they have left the "scope" in which they were defined.

So, the bottom line is that, given a context, we can list the variables it defines. We'll use Ladislav Mecir's context-words? function.

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

Now we can list all the words defined in the global context. (There are a lot of them.)

probe context-words? system/words

We can also write a function that then lists the variables it defines.

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

What we can't do in REBOL, as far as I know, is walk up the context tree, although the interpreter seems to be able to do this perfectly well when it decides how to bind words to their contexts. I think this is because the context tree (i.e., scope) may have one "shape" at the time a word is bound but quite another at the time it's evaluated.

查看更多
小情绪 Triste *
7楼-- · 2019-01-03 01:49

In the R language

ls()

and to remove all objects from the working memory

rm(list=ls(all=TRUE))
查看更多
登录 后发表回答