Перечислите все переменные в программе на [вашем любимом языке здесь] [закрыто]
-
08-07-2019 - |
Вопрос
На прошлой неделе друг спросил меня, как перечислить все переменные в программе / функции / etc.в целях отладки (по сути, получение моментального снимка всего, чтобы вы могли видеть, какие переменные установлены или установлены ли они вообще).Я немного осмотрелся и нашел относительно хороший способ для 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 />'; } ?>
Итак, я изложил это вам:как вы перечисляете все переменные и их содержимое на вашем любимом языке?
Редактировать с помощью ВонК:Я предлагаю, чтобы этот вопрос немного соответствовал духу "код-вызов".
Если вы не согласны, просто отредактируйте и удалите тег и ссылку.
Решение
В 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'>}
Другие советы
Вот как это будет выглядеть в 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"
Однако разве вы не хотели выводить тип объекта, на который ссылается переменная, а не тип, используемый для представления идентификатора переменной? Итак, тип 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
IPython:
whos
Вы также могли бы порекомендовать Спайдер вашему другу, который показывает эти переменные почти так же, как это делает Matlab, и предоставляет графический интерфейс для построчной отладки.
Удар:
set
Отказ от ответственности:Не мой любимый язык!
Полностью рекурсивный однострочный PHP:
print_r(get_defined_vars());
Во-первых, я бы просто использовал отладчик ;-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);
}
}
}
}
Matlab:
who
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, но вы не можете легко получить доступ к локальным переменным метода. Таким образом, следующее не для кода статического анализа, а только для отладки во время выполнения.
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 все переменные находятся внутри context типа object!
. Существует глобальный контекст, и каждая функция имеет свой неявный локальный контекст. Вы можете явно создавать новые контексты, создав новый объект !
(или используя функцию context
). Это отличается от традиционных языков, потому что переменные (называемые «слова» в REBOL) несут с собой ссылку на свой контекст, даже когда они покинули «область». в котором они были определены.
Итак, суть в том, что с учетом контекста мы можем перечислить переменные, которые он определяет. Мы будем использовать <код> слова контекста? функция.
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, насколько я знаю, это пройтись по дереву контекста, хотя интерпретатор, кажется, в состоянии сделать это на отлично, когда решает, как связать слова в их контекстах. Я думаю, что это потому, что дерево контекста (то есть область действия) может иметь одну «форму» в то время как слово связано, но совсем другое в то время, когда оно оценивается.
Быстрое и грязное решение JavaScript, если у вас установлен FireBug (или другой браузер с console.log). Если вы этого не сделаете, вам придется изменить console.log на document.write и запустить в качестве встроенного скрипта в конце вашего. Измените 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))))
Это длинный список, и он не особенно полезен. Я бы действительно использовал встроенный отладчик.
Вот идея для оо-языков.
Сначала вам нужно что-то вроде toString () в Java для печати значимого содержимого. Второе - вы должны ограничить себя одной объектной иерархией. В конструкторе корневого объекта (как Any в Eiffel) вы регистрируете экземпляр при создании в каком-то глобальном списке. Во время уничтожения вы отменяете регистрацию (обязательно используйте некоторую структуру данных, которая позволяет быстро вставлять / искать / удалять). В любое время во время выполнения программы вы можете пройти через эту структуру данных и распечатать все объекты, зарегистрированные там.
Из-за своей структуры Eiffel может быть очень хорош для этой цели. Другие языки имеют проблемы с объектами, которые не определены пользователем (например, jdk-классы). В Java может быть возможно создать свой собственный объектный класс, используя некоторый jdk с открытым исходным кодом.