На прошлой неделе друг спросил меня, как перечислить или перечислить все переменные в программе / функции / и т. д. для целей отладки (по сути, получение снимка всего, чтобы вы могли видеть, какие переменные установлены, или установлены ли они вообще). Я немного огляделся и нашел относительно хороший способ для 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: я предлагаю, что этот вопрос следует духу небольшого "код-вызов" .
Если вы не согласны, просто отредактируйте и удалите тег и ссылку.
В PHP это тоже можно сделать намного проще, см. Мой ответ.
Это хитрость вопроса, потому что он не спрашивает о конкретной проблеме, а говорит: «Давайте посмотрим, что вы можете сделать на вашем языке?». Это дискуссионный вопрос, потому что нет однозначного правильного ответа. Поэтому его, вероятно, следует удалить, но хотя бы пометить вики сообщества. Это больше сообщение на форуме.
Я не согласен, мой план состоит в том, чтобы выбрать наиболее элегантное решение в целом и установить его как ответ и готово. Я полагаю, если бы я задавал один из них для каждого отдельного вопроса, который был бы более квалифицирован как «правильный» вопрос, но стоит отметить, что методы, используемые на разных языках, часто пересекаются с другими языками (т.е. используют отладчик и т. д.).
@MarkRogers, я думал о том же самом. Ответы действительно полезны, но вопрос не так квалифицирован. Я согласен, что он должен идти CW.
отличный пост. Мне это нужно, чтобы получить список переменных, которые я определил в модуле. с добавленным тестом 'not name.startswith (' __ ')' (с использованием python) это творит чудеса для меня. Большое спасибо
Вздох. Не должно быть одновременно: 1) закрытого из-за того, что он слишком широк, потому что он написан на нескольких языках, и 2) как «дублирующего перенаправления» для вопросов на одном языке.
@CharlesMerriam Я согласен, использование этого в качестве цели обмана для конкретных языковых вопросов в основном означает, что «каждый отдельный вопрос о том, как получить список переменных, должен быть закрыт».

Во-первых, я бы просто использовал отладчик ;-p В Visual Studio, например, есть окна «Локальные» и «Наблюдение», в которых будут отображаться все переменные и т. д., Которые вы хотите, с возможностью полного расширения до любого уровня.
В 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);
}
}
}
}
Вот как это будет выглядеть в Рубин:
#!/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"вам также, вероятно, следует включить: instance_variables global_variables константы class_variables
По крайней мере, в Ruby 2.2 мне пришлось использовать, например, instance_variable_get(instance_variables[0])
В 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'>}
В php вы можете сделать это:
$defined = get_defined_vars();
foreach($defined as $varName => $varValue){
echo "$varName is of type ".gettype($varValue)." and has value $varValue <br>";
}
+1 Приятно, эта функция непонятная, но это один из самых маленьких примеров, и некоторые до сих пор говорят, что PHP - отстой. знак равно
В 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");
}
}
}
}
Или вы можете использовать Apache Commons Beanutils.
Многословна не Java, а ваш код. Для начала бессмысленные комментарии плюс полностью устаревшие операции, например вся работа с AccessController не нужна в отдельном приложении (ну, setAccessible в любом случае не нужен для доступа к вашим собственным полям) или в операторе if, чтобы различать два случая, которые можно обрабатывать одинаково при удалении устаревшего вызова toString(): System.out.println(aField.getName() + ": " + res); работает независимо от того, является ли resnull или нет. И нет необходимости распределять код по нескольким методам ...
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";
}
В Lua фундаментальной структурой данных является Таблица, и даже глобальная среда _G представляет собой таблицу. Итак, простое перечисление поможет.
for k,v in pairs(_G) do
print(k..' is '..type(v)..' and is equal to '..tostring(v))
end
Matlab:
who
Общий Лисп:
(do-all-symbols (x) (print x))
Чтобы также показать все связанные значения:
(do-all-symbols (x) (print x) (when (boundp x) (print (symbol-value x))))
Это длинный список, и он не особо полезен. Я бы действительно использовал встроенный отладчик.
Вот идея для oo-языков.
Сначала вам нужно что-то вроде toString () в Java для печати значимого содержимого. Во-вторых, вы должны ограничиться одной иерархией объектов. В конструкторе корневого объекта (например, Any в Eiffel) вы регистрируете экземпляр при создании в каком-то глобальном списке. Во время уничтожения вы отменяете регистрацию (обязательно используйте некоторую структуру данных, которая позволяет быстро вставлять / искать / удалять). В любой момент во время выполнения программы вы можете пройти через эту структуру данных и распечатать все зарегистрированные в ней объекты.
Благодаря своей структуре Эйфель может быть очень хорош для этой цели. На других языках есть проблемы с объектами, которые не определены пользователем (например, jdk-классы). В Java можно было бы создать свой собственный объектный класс, используя какой-нибудь jdk с открытым исходным кодом.
Баш:
set
Отказ от ответственности: не мой любимый язык!
Сравните с env, чтобы узнать, что значения не экспортированы.
В REBOL все переменные находятся внутри контекст типа object!. Есть глобальный контекст, и каждая функция имеет свой собственный неявный локальный контекст. Вы можете явно создавать новые контексты, создав новый object! (или используя функцию context). Это отличается от традиционных языков, потому что переменные (называемые «словами» в REBOL) несут ссылку на свой контекст вокруг себя, даже если они покинули «область действия», в которой они были определены.
Итак, суть в том, что, учитывая контекст, мы можем перечислить переменные, которые он определяет. Мы будем использовать функцию 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 поднимается вверх по контекстному дереву, хотя интерпретатор, кажется, может делать это отлично, когда решает, как связать слова с их контекстами. Я думаю, это связано с тем, что контекстное дерево (т.е. область видимости) может иметь одну «форму» во время связывания слова, но совсем другую во время его оценки.
Полностью рекурсивный однострочник PHP:
print_r(get_defined_vars());
Быстрое и грязное решение JavaScript, если у вас установлен FireBug (или другой браузер с console.info). Если вы этого не сделаете, вам придется изменить console.info на document.write и запустить его как встроенный скрипт в конце вашего. Измените MAX_DEPTH на необходимое количество уровней рекурсии (будьте осторожны!).
(function() {
var MAX_DEPTH = 0;
function printObj(name, o, depth) {
console.info(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))
IPython:
whosВы также можете порекомендовать своему другу Spyder, который показывает эти переменные почти так же, как Matlab, и предоставляет графический интерфейс для построчной отладки.
В python я бы просто использовал locals / globals, а не dir / eval, который вы показываете выше. См. ниже.