Auflisten oder Auflisten aller Variablen in einem Programm von [Ihre Lieblingssprache hier] [geschlossen]


79

Ein Freund hat mich letzte Woche gefragt, wie man alle Variablen in einem Programm / einer Funktion / etc. Auflistet oder auflistet. zum Zwecke des Debuggens (im Wesentlichen um eine Momentaufnahme von allem zu erhalten, damit Sie sehen können, auf welche Variablen gesetzt ist oder ob sie überhaupt gesetzt sind). Ich habe mich ein bisschen umgesehen und einen relativ guten Weg für Python gefunden:

#! / usr / bin / python                                                                                                                                                                                                                           
foo1 = "Hallo Welt"
foo2 = "bar"
foo3 = {"1": "a",
        "2": "b"}
foo4 = "1 + 1"

für den Namen in dir ():
    myvalue = eval (Name)
    Druckname, "ist", Typ (Name), "und ist gleich", myvalue

welches etwas ausgibt wie:

__builtins__ ist <type 'str'> und entspricht <module '__builtin__' (integriert)>
__doc__ ist <Typ 'str'> und ist gleich None
__file__ ist <type 'str'> und entspricht ./foo.py
__name__ ist <type 'str'> und entspricht __main__
foo1 ist <type 'str'> und entspricht Hello world
foo2 ist <type 'str'> und entspricht bar
foo3 ist <Typ 'str'> und ist gleich {'1': 'a', '2': 'b'}
foo4 ist <Typ 'str'> und ist gleich 1 + 1

Ich habe bisher einen Teilweg in PHP gefunden (mit freundlicher Genehmigung von Linktext ), aber es werden nur alle Variablen und ihre Typen aufgelistet, nicht der Inhalt:

<? php
// ein paar Variablen erstellen
$ bar = 'foo';
$ foo = 'bar';
// Erstelle ein neues Array Objekt
$ arrayObj = neues ArrayObject (get_defined_vars ());
// Schleife über das Array-Objekt und Echo-Variablen und -Werte
für ($ iterator = $ arrayObj-> getIterator (); $ iterator-> valid (); $ iterator-> next ())
        {
        echo $ iterator-> key (). '=>'. $ iterator-> current (). '<br />';
        }}
?>

Also sage ich es Ihnen: Wie listen Sie alle Variablen und ihren Inhalt in Ihrer Lieblingssprache auf?


Edit von VonC : Ich schlage vor, diese Frage folgt dem Geist einer kleinen " Code-Herausforderung ".
Wenn Sie nicht einverstanden sind, bearbeiten und entfernen Sie einfach das Tag und den Link.


4
In Python würde ich nur Einheimische / Globale anstelle des oben gezeigten Verzeichnisses / Evals verwenden. Siehe unten.
Aaron Maenpaa

In PHP kann es auch viel einfacher gemacht werden, siehe meine Antwort.
Pim Jäger

1
Ich bin anderer Meinung, mein Plan ist es, die eleganteste Lösung insgesamt zu wählen und diese als Antwort und Presto festzulegen. Ich nehme an, wenn ich für jede einzelne Frage eine dieser Fragen gestellt hätte, die sich eher als "richtige" Frage qualifizieren würde, aber es ist erwähnenswert, dass sich die in verschiedenen Sprachen verwendeten Methoden häufig mit anderen Sprachen überschneiden (dh den Debugger / etc. Verwenden).
Kurt

1
guter Eintrag. Ich brauchte dies, um eine Liste der Variablen zu erhalten, die ich in einem Modul definiert habe. Mit einem zusätzlichen Test von 'not name.startswith (' __ ')' (mit Python) tut dies Wunder für mich. Vielen Dank
ShadowFlame

2
Seufzer. Sollte nicht beides sein, 1) geschlossen sein, weil es zu breit ist, weil es mehrere Sprachen hat, und 2) die "doppelte Weiterleitung" für Fragen einer einzigen Sprache sein.
Charles Merriam

Antworten:


93

Verwenden Sie in Python Locals, die ein Wörterbuch zurückgeben, das alle lokalen Bindungen enthält, und vermeiden Sie so die Auswertung:

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

11

So würde es in Ruby aussehen :

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

welches ausgegeben wird

foo1 ist String und entspricht "Hallo Welt"
foo2 ist String und ist gleich "bar"
foo3 ist String und ist gleich {"1" => "a", "2" => "b"}
foo4 ist String und ist gleich "1 + 1"

Wollten Sie jedoch nicht den Objekttyp ausgeben, auf den die Variablen verweisen, anstatt den Typ, der zur Darstellung der Variablenkennung verwendet wird? IOW, die Art von foo3sollte Hash(oder dict) statt sein String, oder? In diesem Fall wäre der Code

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

und das Ergebnis ist

foo1 ist String und entspricht "Hallo Welt"
foo2 ist String und ist gleich "bar"
foo3 ist Hash und ist gleich {"1" => "a", "2" => "b"}
foo4 ist String und ist gleich "1 + 1"

1
Sie sollten wahrscheinlich auch Folgendes einschließen: instance_variables global_variables class_variables constants
Rado

Zumindest in Ruby 2.2 musste ich zBinstance_variable_get(instance_variables[0])
jberryman

10

IPython:

whos

Sie können Spyder auch Ihrem Freund empfehlen , der diese Variablen ähnlich wie Matlab anzeigt und eine grafische Benutzeroberfläche für das zeilenweise Debuggen bietet.


9

In PHP könnten Sie dies tun:

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

3
+1 Schön, diese Funktion ist etwas dunkel, aber dies ist eines der kleinsten Beispiele hier, und einige sagen immer noch, PHP sei scheiße. =)
Alix Axel

9

In Lua ist die grundlegende Datenstruktur die Tabelle und sogar die globale Umgebung _G ist eine Tabelle. Eine einfache Aufzählung reicht also aus.

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

6

Bash:

set

Haftungsausschluss: Nicht meine Lieblingssprache!


3
Vergleichen Sie mit env, um herauszufinden, welche Werte nicht exportiert wurden.
Nitrodist

6

Ein vollständig rekursiver PHP-Einzeiler:

print_r(get_defined_vars());

4

Erstens würde ich einfach einen Debugger verwenden ;-p Visual Studio verfügt beispielsweise über die Fenster "Locals" und "Watch", in denen alle gewünschten Variablen usw. angezeigt werden und die auf jede Ebene vollständig erweiterbar sind.

In C # kann man nicht sehr einfach auf Methodenvariablen zugreifen (und viele davon können vom Compiler entfernt werden) - aber Sie können über Reflektion auf Felder usw. zugreifen:

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

Perl. Behandelt keine myEinheimischen und filtert keine nutzlosen Referenzen heraus, aber alles im Paketumfang ist sichtbar.

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

In der R-Sprache

ls()

und um alle Objekte aus dem Arbeitsspeicher zu entfernen

rm(list=ls(all=TRUE))

2

In Java wäre das Problem ähnlich wie in C #, nur in einem ausführlicheren Modus (ich weiß, ich weiß ;) Java ist ausführlich ... das haben Sie bereits klargestellt;) )

Sie können über Refection auf Objektfelder zugreifen, aber möglicherweise nicht einfach auf lokale Methodenvariablen. Das Folgende gilt also nicht für statischen Analysecode, sondern nur für das Laufzeit-Debugging.

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

Oder Sie können Apache Commons Beanutils verwenden.
Aaron Digulla

Es ist nicht Java, das ausführlich ist, sondern Ihr Code. Zunächst bedeutungslose Kommentare sowie völlig veraltete Vorgänge, z. B. ist der gesamte Umgang mit AccessControllereiner eigenständigen Anwendung nicht erforderlich (naja, es setAccessibleist ohnehin nicht erforderlich, auf Ihre eigenen Felder zuzugreifen) oder die ifAnweisung, zwischen zwei Fällen zu unterscheiden, die behandelt werden können Genauso wie beim Entfernen des veralteten toString()Aufrufs: Funktioniert System.out.println(aField.getName() + ": " + res);, unabhängig davon, ob dies der Fall resist nulloder nicht. Und es ist auch nicht nötig, den Code auf mehrere Methoden zu verteilen ...
Holger

1

In REBOL, leben alle Variablen in einem Kontext von Art object!. Es gibt einen globalen Kontext und jede Funktion hat ihren eigenen impliziten lokalen Kontext. Sie können explizit neue Kontexte erstellen, indem Sie einen neuen erstellen object!(oder die contextFunktion verwenden). Dies unterscheidet sich von herkömmlichen Sprachen, da Variablen (in REBOL "Wörter" genannt) einen Verweis auf ihren Kontext mit sich führen, selbst wenn sie den "Bereich" verlassen haben, in dem sie definiert wurden.

Unter dem Strich können wir also in einem bestimmten Kontext die darin definierten Variablen auflisten. Wir werden die context-words?Funktion von Ladislav Mecir verwenden.

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

Jetzt können wir alle im globalen Kontext definierten Wörter auflisten. (Es gibt viele von ihnen.)

probe context-words? system/words

Wir können auch eine Funktion schreiben, die dann die von ihr definierten Variablen auflistet.

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

Was wir in REBOL meines Wissens nicht tun können , ist den Kontextbaum hochzugehen, obwohl der Interpreter dies anscheinend perfekt kann, wenn er entscheidet, wie Wörter an ihre Kontexte gebunden werden. Ich denke, das liegt daran, dass der Kontextbaum (dh der Bereich) zum Zeitpunkt der Wortbindung eine "Form" haben kann, zum Zeitpunkt der Auswertung jedoch eine ganz andere.


1

Schnelle und schmutzige JavaScript-Lösung, wenn Sie FireBug installiert haben (oder einen anderen Browser mit console.log). Wenn Sie dies nicht tun, müssen Sie console.log in document.write ändern und am Ende Ihres als Inline-Skript ausführen. Ändern Sie MAX_DEPTH auf die gewünschte Rekursionsstufe (Vorsicht!).

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

0

Common Lisp:

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

So zeigen Sie auch alle gebundenen Werte an:

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

Dies ist eine lange Liste und nicht besonders nützlich. Ich würde wirklich den integrierten Debugger verwenden.


0

Hier ist eine Idee für oo-Sprachen.

Zuerst benötigen Sie so etwas wie toString () in Java, um aussagekräftige Inhalte zu drucken. Zweitens müssen Sie sich auf eine Objekthierarchie beschränken. Im Konstruktor des Root-Objekts (wie Any in Eiffel) registrieren Sie die Instanz beim Erstellen in einer Art globaler Liste. Während der Zerstörung melden Sie sich ab (stellen Sie sicher, dass Sie eine Datenstruktur verwenden, die ein schnelles Einfügen / Suchen / Entfernen ermöglicht). Während der Programmausführung können Sie jederzeit durch diese Datenstruktur gehen und alle dort registrierten Objekte drucken.

Aufgrund seiner Struktur könnte Eiffel für diesen Zweck sehr gut geeignet sein. Andere Sprachen haben Probleme mit Objekten, die nicht benutzerdefiniert sind (z. B. die JDK-Klassen). In Java ist es möglicherweise möglich, eine eigene Objektklasse mit einem Open-Source-JDK zu erstellen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.