Wylicz lub wylistuj wszystkie zmienne w programie [Twój ulubiony język tutaj] [zamknięty]

Znajomy zapytał mnie w zeszłym tygodniu, jak wyliczyć lub wymienić wszystkie zmienne w programie/funkcji/itp. do celów debugowania (zasadniczo uzyskanie migawki wszystkiego, dzięki czemu można zobaczyć, jakie zmienne są ustawione lub czy są ustawione w ogóle). Rozejrzałem się trochę i znalazłem stosunkowo dobry sposób na Pythona:

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

Który wyświetli coś w stylu:

__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

Do tej pory znalazłem częściową drogę w PHP (dzięki uprzejmości link text), ale wyświetla tylko wszystkie zmienne i ich rodzaje, a nie treść:

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

Więc powiem Ci: jak wylistować wszystkie zmienne i ich zawartość w Twoim ulubionym języku?


Edit by VonC : proponuję, aby to pytanie było zgodne z duchem małego " code-challenge ".
Jeśli nie zgadzasz się, po prostu Edytuj i Usuń tag i link.

Author: Community, 2009-01-10

16 answers

W Pythonie, używając locals, który zwraca słownik zawierający wszystkie lokalne powiązania, unikając w ten sposób 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'>}
 83
Author: Aaron Maenpaa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-10 11:30:39

Tak by to wyglądało w 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

Który wyświetli

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"

Nie chodziło Ci jednak o wypisanie typu obiektu, do którego odwołuje się zmienna, zamiast typu używanego do reprezentowania identyfikatora zmiennej? IOW, Typ foo3 powinien być Hash (lub dict) zamiast String, prawda? W takim przypadku kod będzie

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

A wynikiem jest

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"
 11
Author: Jörg W Mittag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-20 13:27:26

W php możesz to zrobić:

$defined = get_defined_vars(); 
foreach($defined as $varName => $varValue){
 echo "$varName is of type ".gettype($varValue)." and has value $varValue <br>";
}
 9
Author: Pim Jager,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-10 13:17:46

W Lua podstawową strukturą danych jest Tabela , a nawet globalne środowisko _G jest tabelą. Tak więc proste wyliczenie wystarczy.

for k,v in pairs(_G) do
  print(k..' is '..type(v)..' and is equal to '..tostring(v))
end
 9
Author: Nick Dandoulakis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-23 18:28:11

Bash:

set

Disclaimer: Nie Mój ulubiony język!

 6
Author: too much php,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-26 05:01:44

W pełni rekurencyjny jednowiersz PHP:

print_r(get_defined_vars());
 6
Author: LapTop006,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-26 11:24:21

IPython:

whos

Możesz również polecić Spyder swojemu znajomemu, który pokazuje te zmienne prawie tak, jak robi to Matlab i dostarcza GUI do debugowania linia po linii.

 5
Author: Eder Santana,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-06 21:29:37

Po Pierwsze, po prostu użyłbym debuggera ; - p Na przykład Visual Studio ma okna "Locals" i "Watch", które pokażą wszystkie zmienne itp., które chcesz, w pełni rozszerzalne do dowolnego poziomu.

W C# tak naprawdę nie można łatwo dostać się do zmiennych metody ( a wiele z nich jest dobrze usuwanych przez kompilator) - ale można uzyskać dostęp do pól itp poprzez odbicie:

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);
            }
        }
    }
}
 4
Author: Marc Gravell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-10 10:03:01

Matlab:

who
 4
Author: Dario,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-23 18:49:02

Perl. Nie obsługuje my lokalnych i nie odfiltrowuje bezużytecznych referencji, ale wszystko w zakresie pakietu może być widoczne.

my %env = %{__PACKAGE__ . '::'};
while (($a, $b) = each %env) {
    print "\$$a = $$b\n";
    print "\@$a = (@$b)\n";
    print "%$a = (@{[%$b]})\n";
    print "*$a = $b\n";
}
 3
Author: ephemient,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-19 16:42:59

W Javie problem byłby podobny do C#, tylko w bardziej wyrazistym trybie (wiem, wiem. ;) Java jest gadatliwa... Już to wyjaśniłeś.;) )

Możesz uzyskać dostęp do pól obiektu poprzez Refekcję, ale możesz nie mieć łatwego dostępu do zmiennych lokalnych metody. Tak więc poniższe informacje nie dotyczą kodu analizy statycznej, ale tylko debugowania w trybie runtime.

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");
            }
        }
    }
}
 2
Author: VonC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:50

W języku R

ls()

Oraz aby usunąć wszystkie obiekty z pamięci roboczej

rm(list=ls(all=TRUE))
 2
Author: Tiago Zortea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-06 20:28:52

W REBOLU wszystkie zmienne ĹźyjÄ ... wewnÄ ... trz kontekstu typu object!. Istnieje kontekst globalny, a każda funkcja ma swój własny, niejawny kontekst lokalny. Nowe konteksty można tworzyć jawnie, tworząc nową object! (lub używając funkcji context). Jest to róşne od jÄ ™ zykĂłw tradycyjnych, poniewaĹź zmienne (nazywane w REBOLU" sĹ 'owa") niosÄ ... ze sobÄ ... referencjÄ ™ do swojego kontekstu, nawet jeĹ "li pozostawiĺ 'y" zakres", w ktĂłrym zostaĹ ' y zdefiniowane.

Więc najważniejsze jest to że, biorąc pod uwagę kontekst, możemy wymienić zmienne, które definiuje. Użyjemy Ladislava Mecira context-words? funkcja.

context-words?: func [ ctx [object!] ] [ bind first ctx ctx ]

Teraz możemy wymienić wszystkie słowa zdefiniowane w kontekście globalnym. (Istnieje wiele z nich.)

probe context-words? system/words

Możemy również napisać funkcję, która następnie wyświetla listę zmiennych, które definiuje.

enumerable: func [a b c /local x y z] [
  probe context-words? bind? 'a
]

To, czegonie potrafimy w REBOLU, z tego co wiem, to wspinanie się po drzewie kontekstu, chociaż interpreter wydaje się być w stanie zrobić to doskonale kiedy decyduje, jak powiązać słowa z ich kontekstami. Myślę, że dzieje się tak dlatego, że drzewo kontekstu (tj. zakres) może mieć jeden "kształt" w czasie, gdy słowo jest związane, ale zupełnie inny w czasie, gdy jest oceniane.

 1
Author: Gregory Higley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-26 08:54:01

Szybkie i brudne rozwiązanie JavaScript, jeśli masz zainstalowany FireBug (lub inną przeglądarkę z konsolą.log). Jeśli tego nie zrobisz, będziesz musiał zmienić konsolę.Zaloguj się do dokumentu.napisz i uruchom jako skrypt wbudowany na końcu swojego . Zmień MAX_DEPTH na ile poziomów rekurencji chcesz (bądź ostrożny!).

(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);
    }
})();
 1
Author: gregers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-26 20:12:40

Common Lisp:

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

Aby również pokazać wszystkie wartości związane:

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

To długa lista i niezbyt przydatna. Naprawdę użyłbym zintegrowanego debuggera.

 0
Author: Svante,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-23 19:03:51

Oto pomysł na OO-języki.

Najpierw potrzebujesz czegoś takiego jak toString() w Javie, aby wydrukować znaczącą zawartość. Po drugie-musisz ograniczyć się do jednego obiektu-hierarchii. W konstruktorze root-object (jak każdy w Eiffel), rejestrujesz instancję podczas tworzenia w jakiejś globalnej liście. Podczas niszczenia wyrejestrowujesz się (pamiętaj, aby użyć jakiejś struktury danych, która umożliwia szybkie wstawianie / wyszukiwanie / usuwanie). W każdej chwili podczas wykonywania programu można przejść przez ta struktura danych i wypisuje wszystkie zarejestrowane tam obiekty.

Ze względu na swoją strukturę, Eiffel może być bardzo dobry do tego celu. Inne języki mają problemy z obiektami, które nie są zdefiniowane przez użytkownika (np. klasy jdk). W Javie może być możliwe utworzenie własnej klasy obiektowej przy użyciu jakiegoś open-source jdk.

 0
Author: Tobias Langner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-25 16:19:26