2015-06-24 6 views
12

Ich habe folgendes Snippet:Python: Problem, wenn Vars() verwenden Wörterbuch

a, b = 1, 2 
params = ['a', 'b'] 
res = {p: vars()[p] for p in params} 

Was mich KeyError: 'a' gibt während der folgende Code funktioniert:

a, b = 1, 2 
params = ['a', 'b'] 
res = {} 
for p in params: 
    res[p] = vars()[p] 

Was ist der Unterschied hier?

+2

Sie fragen, weil Sie neugierig sind, nicht, weil Sie auf 'Vars verlassen()'/'Einheimischen() 'in deinen tatsächlichen Programmen, richtig? – TigerhawkT3

+0

@ TigerhawkT3: jetzt, nachdem Sie gefragt haben, würde ich nur aus Neugier sagen :) – Ulysses

Antwort

9

vars() ohne Argument wirkt wie locals() und da ein Wörterbuch Verständnis seiner eigenen Anwendungsbereich hat es keine variable a oder b genannt.

Sie können eval() hier verwenden. Ohne Argument wird es in LEGB Weise auszuführen, oder geben Sie globals() dict explizit eval:

>>> res = {p: eval(p) for p in params} 
>>> res 
{'a': 1, 'b': 2} 

Aber dann wieder die richtige Art und Weise wird ein Wörterbuch von Anfang an erstellen, wenn Sie den Zugriff auf Variablen verwenden möchten ihre Namen.

+0

Was wäre der Weg, um es zu beheben, wenn ich nicht durch eine Multi-Line-Schleife gehen möchte? – Ulysses

+3

Der beste Weg, um es zu beheben, besteht darin, ein Durcheinander mit 'vars()'/'localhosts()' insgesamt zu vermeiden, weil sie Ihnen Probleme wie diese geben werden. – TigerhawkT3

+1

Ich benutze 'vars()' nur mit 'format': es ist einfach zu attraktiv,' 'foo {bar} baz {spam} 'zu schreiben. Format (** vars())' anstatt '.format (bar = bar , Spam = Spam) '.Aber es geht falsch innerhalb eines Verständnisses. @ TigerhawkT3 was würdest du als Pythonic Alternative zu meinem '.format (** vars())' code empfehlen? – gerrit

5

Sein wegen, dass in Ihrem Code vars ein Wörterbuch, um die lokalen variables.actually auf Dokumentation basiert gibt enthält:

Ohne Argument, vars() wirkt wie locals().

siehe folgendes Beispiel:

>>> def a(): 
... print vars() 
... 
>>> a() 
{} 

Wie Sie wir haben keine lokale Variable in Funktion sehen a so Vars gibt ein leeres Wörterbuch.

Und in Ihrem Fall als mehr pythonic Art und Weise Sie ein Wörterbuch Ihrer Objekte erstellen:

d={'a':1,'b': 2,'params' : ['a', 'b']} 
example_list : ['a', 'b'] 
res = {p: d[p] for p in example_list} 
3

Es scheint Python einen Verschluss im Wörterbuch Verständnis macht (etwa dictcomp)

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 1, in <dictcomp> 
KeyError: 'a' 
3

Verwenden Sie vars() in der for-Schleife als den zweiten Code, den Sie angegeben haben.

# come out with {'a': 1, 'b': 2} 
res = {p: v for p, v in vars().iteritems() if p in params} 
res = {'a': vars()['a'], 'b': vars()['b']} 

Wir können die neuen locals/vars innerhalb for Schleife in dict Verständnis herauszufinden:

>>> {i: list(vars().viewkeys()) if i == 0 else list(vars().viewvalues()) for i in range(2)} 
{0: ['i', '.0'], 1: [1, <listiterator at 0x6fffe458550>]} 
>>> {list(vars().viewkeys())[i]: list(vars().viewvalues())[i] for i in range(2)} 
{'.0': <listiterator at 0x6fffe458710>, 'i': 0}