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