Подтвердить что ты не робот

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

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

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


Изменить VonC: Я предлагаю этот вопрос следовать духу небольшого "code-challenge".
Если вы не согласны, просто отредактируйте и удалите тег и ссылку.

4b9b3361

Ответ 1

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

Ответ 2

Это будет выглядеть в 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"

Однако, вы не хотите выводить тип объекта вместо ссылки на переменные вместо типа, используемого для представления идентификатора переменной? 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 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"

Ответ 3

В php вы можете сделать это:

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

Ответ 4

В Lua фундаментальной структурой данных является таблица и даже глобальная среда _G - это таблица. Итак, простое перечисление сделает трюк.

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

Ответ 5

Bash:

set

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

Ответ 6

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

print_r(get_defined_vars());

Ответ 7

Сначала я просто использовал отладчик; -p Visual Studio, например, имеет окна "Locals" и "Watch", которые будут отображать все переменные и т.д., Которые вы хотите, полностью расширяемые на любой уровень.

В С# вы не можете очень легко получить переменные метода (и многие из них будут удалены компилятором), но вы можете получить доступ к полям и т.д. через отражение:

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

Ответ 8

Matlab:

who

Ответ 9

IPython:

whos

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

Ответ 10

Perl. Не обрабатывает locals 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

В java проблема будет похожа на С#, только в более подробном режиме (я знаю, Я ЗНАЮ;) Java verbose... вы уже поняли это;))

Вы можете получить доступ к объектным полям через 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");
            }
        }
    }
}

Ответ 12

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

Ответ 13

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

Ответ 14

В языке R

ls()

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

rm(list=ls(all=TRUE))

Ответ 15

Общий Lisp:

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

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

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

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

Ответ 16

Здесь идея оо-языков.

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

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