Перечислите или Перечислите все переменные в программе [ваш любимый язык здесь] [закрыто]


подруга попросила меня на прошлой неделе, как перечислять и перечислять все переменные внутри программы/функции/и т. д. для целей отладки (по сути, получение моментального снимка всего, чтобы вы могли видеть, какие переменные установлены, или если они установлены вообще). Я немного огляделся и нашел относительно хороший способ для 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 (любезно текст ссылки), но это только перечисляет все переменные и их типы, а не содержимое:

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

Итак, я говорю вам: как вы перечисляете все переменные и их содержимое на своем любимом языке?


Edit by VonC: я предлагаю, чтобы этот вопрос следовал духу небольшого "кода-вызова".
Если вы не согласны, измените и удалите тег и ссылку.

16 69

16 ответов:

в 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'>}

вот как это будет выглядеть в Рубин:

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

в 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

отказ от ответственности: не мой любимый язык!

полностью рекурсивный PHP однострочный:

print_r(get_defined_vars());

IPython:

whos

вы также можете рекомендовать Spyder вашему другу, который показывает эти переменные в значительной степени, как это делает Matlab, и предоставляет графический интерфейс для построчной отладки.

во-первых, я бы просто использовал отладчик ; - 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);
            }
        }
    }
}

Matlab:

who

Perl. Не справляется my locals, и не отфильтровывает некоторые бесполезные ссылки, но все в области пакета можно увидеть.

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 многословен... вы уже ясно дали это понять;))

вы можете получить доступ к полям объектов через отражение, но вы не можете легко получить доступ к локальным переменным метода. Таким образом, следующее относится не к коду статического анализа, а только к отладке во время выполнения.

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

на языке R

ls()

и удалить все объекты из рабочей памяти

rm(list=ls(all=TRUE))

в REBOL, все переменные живут внутри контекст типа object!. Существует глобальный контекст, и каждая функция имеет свой собственный неявный локальный контекст. Вы можете создать новые контексты явно, создав новый object! (или с помощью

быстрое и грязное решение JavaScript, если у вас установлен FireBug (или другой браузер с консолью.бревно.) Если вы этого не сделаете, вам придется сменить консоль.войти в документ.напишите и запустите в качестве встроенного скрипта в конце вашего . Измените 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);
    }
})();

Common Lisp:

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

показать все связанные значения:

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

Это длинный список, и не особенно полезно. Я бы действительно использовал интегрированный отладчик.

вот идея для oo-языков.

сначала вам нужно что-то вроде toString() в Java для печати значимого содержимого. Второе-вы должны ограничиться одним объектом-иерархией. В конструкторе корневого объекта (как и любой в Eiffel), вы регистрируете экземпляр при создании в каком-то глобальном списке. Во время уничтожения вы отменяете регистрацию (обязательно используйте некоторую структуру данных, которая позволяет быстро вставлять / искать / удалять). Любое время во время выполнения программы, вы можете прогуляться через эту структуру данных и выводятся все зарегистрированные там объекты.

из-за его структуры, Эйфель может быть очень хорошо для этой цели. Другие языки имеют проблемы с объектами, которые не определены пользователем (например, JDK-классы). В Java можно было бы создать свой собственный класс объектов, используя некоторый jdk с открытым исходным кодом.