2010-02-23 7 views
20

ich es sehr nützlich, neue Variablen in der Lage sein zu finden zuweisen während der Laufzeit zu erstellen und ein Wörterbuch der Ergebnisse für die Verarbeitung später erstellen, das heißt in eine Datei schreiben:Python: Verwenden von Vars() einen String in eine Variable

myDict = {} 
for i in range (1,10): 
    temp = "variable"+str(i) 
    vars()[temp] = myFunctionThatReturnsData() # variable1= data1, variable2 = data2,etc. 
    myDict[temp] = vars(temp) 

erstellt den Wörterbucheintrag [result1: data1], den ich mit myDict aufrufen kann [result1]. Ich habe vars() benutzt, ohne wirklich zu verstehen, was ich mache. Ich nehme es vars() ein Wörterbuch mit den lokalen Variablen zurückgibt, und

Vars() [x] = y

erstellt einen neuen Wörterbucheintrag von [x: y] (?)?

Ich habe ein Skript, wo ich ein Wörterbuch mit {input1: data1, input2: data2} übergeben, und ich verwende diese Methode, um alle Werte zu durchlaufen, speichern Sie alle Ergebnisse und geben Sie es in eine Datei. Dieses Codebeispiel befindet sich innerhalb einer Funktion innerhalb einer Klasse und funktioniert.

Meine Quelle der Verwirrung ist, dass ich in verschiedenen Funktionen, wie die Einheimischen gelesen haben() sollte nicht mit verwirrt werden, und wie vars() entspricht (?) Zu Einheimischen() oder Globals() ..

Also meine Frage ist (mindestens) zweifach:

1.What genau funktioniert vars(), oder insbesondere in vars() [x] = y, tun

2.What den Anwendungsbereich von diesem Wörterbuch ist (was ich beachten muss, während ich größere Programme schreibe

3.Whit das ist gute Programmierung trainieren.

Vielen Dank im Voraus!

Antwort

32

Die pythonic Art und Weise eine Folge von Variablen

Wenn Sie eine Folge von Variablen wollen, erstellen Sie eine Sequenz zu erstellen. Anstelle der unabhängigen Variablen zu erstellen versuchen, wie:

variable0 
variable1 
variable2 
variable3 

Sie auf die Schaffung eines list aussehen sollte. Dies ist ähnlich zu dem, was S.Lott vorschlägt (S.Lott hat in der Regel ein guter Rat), aber Karten mehr ordentlich auf Ihre for Schleife.

sequence = [] 
for _ in xrange(10): 
    sequence.append(function_that_returns_data()) 

(Beachten Sie, dass wir die Schleifenvariable (_) verwerfen Wir wieder nur 10 Pässe zu bekommen versuchen)

Ihre Daten dann als zur Verfügung stehen wird.

sequence[0] 
sequence[1] 
sequence[2] 
sequence[3] 
[...] 
sequence[9] 

als zusätzlichen Bonus können Sie tun:

for datum in sequence: 
    process_data(datum) 

Zuerst können Sie zucken, wenn Ihre Sequenz bei 0 beginnt. Sie können verschiedene Verrenkungen durchgehen, um Ihre tatsächlichen Daten bei 1 zu beginnen, aber es ist mehr Schmerz als es wert ist. Ich empfehle nur, sich an Null-basierte Listen zu gewöhnen. Alles ist um sie herum gebaut, und sie beginnen, sich ziemlich schnell natürlich zu fühlen.

Vars() und Einheimischen()

, nun einen weiteren Teil Ihrer Frage zu beantworten. vars() (oder locals()) bietet Low-Level-Zugriff auf von Python erstellte Variablen. Somit sind die folgenden zwei Zeilen äquivalent.

locals()['x'] = 4 
x = 4 

Der Umfang der vars()['x'] ist genau der gleiche wie der Umfang der x. Ein Problem mit locals() (oder vars()) ist, dass Sie Dinge in den Namespace legen können, die Sie nicht aus dem Namespace auf normale Weise erhalten können. Sie können also etwas wie folgt tun: locals()[4] = 'An integer', aber Sie können das nicht wieder zurückholen, ohne Locals erneut zu verwenden, da der lokale Namespace (wie bei allen Python-Namespaces) nur dazu dient, Strings zu speichern.

>>> x = 5 
>>> dir() 
['__builtins__', '__doc__', '__name__', 'x'] 
>>> locals()[4] = 'An integer' 
>>> dir() 
[4, '__builtins__', '__doc__', '__name__', 'x'] 
>>> x 
5 
>>> 4 
4 
>>> locals()[4] 
'An integer' 

Beachten Sie, dass 4 nicht das gleiche wie Locals() [4] zurückgibt. Dies kann zu einigen unerwarteten, schwer zu debuggenden Problemen führen. Dies ist ein Grund, die Verwendung von locals() zu vermeiden.Ein anderes ist, dass es im Allgemeinen eine Menge Komplikationen ist, nur Dinge zu tun, die Python einfacher und weniger fehleranfällig bietet (wie das Erstellen einer Sequenz von Variablen).

+2

Ich denke 'vars() ['x'] = 4' und' x = 4' sind eigentlich nur zeitweise äquivalent. Wenn Sie dies in einer Funktion tun und 'x' nicht an anderer Stelle setzen und die Funktion vom Compiler optimiert wird, dann hat das normale Nachschlagen von' x' später in der Funktion (dh, y = x + 2') gewonnen arbeite nicht. Ich denke, der Compiler speichert die Variablen, die er sehen kann (wurden möglicherweise zur Kompilierungszeit definiert), und berücksichtigt diese Art von Shenanigan nicht. Wenn Sie Ihrer Funktion eine exec-Anweisung hinzufügen, versucht der Compiler nicht, die Funktion zu optimieren. –

+1

danke für die nachdenkliche antwort, für das daten in folge: funktion (daten) sieht sehr nützlich aus. Es gibt eine Menge hier, die ich heute gelernt habe, danke! – PPTim

+0

Um weitere Informationen zu diesem Konstrukt zu erhalten, suchen Sie nach "python iterators" – jcdyer

2

Ich kann Nummer 3 beantworten: das ist keine gute Programmierpraxis. Ich sehe nicht genau, was Sie zu erreichen versuchen, aber ich bin mir sicher, dass es eine elegantere Vorgehensweise gibt, ohne locals() zu verwenden (das ist dasselbe wie vars() nach help(vars) in der interaktiven Python-Shell).

5

Von der Hilfe für Vars,

Vars (...) Vars ([object]) -> Wörterbuch

Without arguments, equivalent to locals(). 
With an argument, equivalent to object.__dict__. 

Du es ohne Vars verwenden, so lasst uns Blick auf die Hilfe für die Einheimischen()

Einheimischen (...) Einheimischen() -> Wörterbuch

Update and return a dictionary containing the current scope's local 

Variablen.

So beantwortet dies die ersten zwei Fragen. vars() gibt ein Dictionary an die lokalen Variablen zurück, das durch den Namen der Variablen als String indiziert wird. Der Umfang ist lokal.

Ich bin mir nicht sicher über die dritte Frage, aber es scheint wie eine Art von Hack, die kein gutes Zeichen ist.Ich schätze, wenn Sie vorsichtig sind, dies nur im richtigen Umfang zu verwenden, können Sie damit klar kommen.

+0

ich in meiner Verwirrung, so verfing vergaß ich um Hilfe zu bitten(). Danke, – PPTim

6

Tun Sie dies stattdessen. Es ist einfacher.

myDict = {} 
for i in range (1,10): 
    temp = "variable"+str(i) 
    myDict[temp] = myFunctionThatReturnsData() # variable1= data1, variable2 = data2,etc. 

Das ist alles, was Sie jemals tun müssen.

Die Ergebnisse werden myDict['variable1'] durch myDict['variable9']

Sie selten vars() oder locals() müssen sein. Hör einfach auf, sie zu benutzen, und benutze gewöhnliche Variablen und gewöhnliche Wörterbücher. Versuche Dinge zu vermeiden, die du nicht verstehst, und halte dich an die einfachen, offensichtlichen Dinge.

+0

Nun, da ich darüber nachdenke, warum ich vars() benutzt habe, lag es wahrscheinlich daran, dass es sich gut anfühlte, die Variablen direkt von IDLE aufrufen zu können, wenn ich den Code Zeile für Zeile ausprobierte. Danke für die Antwort! – PPTim

1

Die Verwendung von Vars/Locals oder Globals auf diese Weise ist (a) eine schlechte Übung und (b) funktioniert nicht in allen Fällen. Weitere Details finden Sie unter Dynamically set local variable. Fazit: Benutze nur dicts - dafür sind sie da.

4

jcdyer erklärt die Konzepte sehr gut und Justin Peel gibt eindeutig an, was vars() und locals() tun. Aber ein kleines Beispiel beschleunigt immer das Verständnis.

class Bull(object): 

    def __init__(self): 
     self.x = 1 
     self.y = "this" 

    def __repr__(self): 
     return "Bull()" 

    def test1(self): 
     z = 5 
     return vars() 

    def test2(self): 
     y = "that" 
     return vars(self) 

    def test3(self): 
     return locals() 

    def test4(self): 
     y = 1 
     return locals() 

if __name__ == "__main__": 
    b = Bull() 
    print b.test1() 
    print b.test2() 
    print b.test3() 
    print b.test4() 
    print vars(b).get("y") 

was zur Folge hat:

{'self': Bull(), 'z': 5} 
{'y': 'this', 'x': 1} 
{'self': Bull()} 
{'y': 1, 'self': Bull()} 
this 
Verwandte Themen