2015-06-24 3 views
12

У меня есть следующий фрагмент кода:Python: проблема при использовании ВАРА() словарь

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

Который дает мне KeyError: 'a' тогда следующий код работает отлично:

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

Какая разница здесь?

+2

Вы спрашиваете, потому что вам интересно, а не потому, что вы полагаетесь на 'Варс()'/'местные жители() 'в ваших реальных программах, не так ли? – TigerhawkT3

+0

@ TigerhawkT3: теперь, после того, как вы спросили, я скажу исключительно из-за любопытства :) – Ulysses

ответ

9

vars() без каких-либо аргументов действует как locals() и так как словарь понимания имеет свою область применения он не имеет переменную с именем a или b.

Здесь вы можете использовать eval(). Без какого-либо аргумента он будет выполняться в LEGB образом, или указать globals() Dict явно eval:

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

Но затем снова правильный путь будет создать словарь с самого начала, если вы хотите получить доступ к переменным, используя их имена.

+0

Каким образом это исправить, если я не хочу проходить многострочный цикл? – Ulysses

+3

Лучший способ исправить это, чтобы избежать беспорядка с 'vars()'/'locals()' вообще, потому что они будут давать вам такие проблемы, как этот. – TigerhawkT3

+1

Я использую 'vars()' с 'format': это слишком привлекательно для записи' 'foo {bar} baz {spam} '. Format (** vars())', а не '.format (bar = bar , спам = спам) '.Но это происходит неправильно в понимании. @ TigerhawkT3, что бы вы рекомендовали в качестве альтернативы Pythonic для моего кода .format (** vars())? – gerrit

5

Его из-за этого в коде vars возвращает словарь содержит местного variables.actually на основе документации:

Без аргумента, vars() действует как locals().

следующий пример:

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

Как вы можете видеть, что мы не какой-либо локальной переменной внутри функции a так VARS возвращает пустой словарь.

А в вашем случае, как более вещий образом вы можете создать словарь ваших объектов:

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

кажется Python делает замыкание в словаре понимания (скажем, dictcomp)

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

Использовать vars() в цикле for выполняет второй код, который вы указали.

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

Мы можем выяснить, новый locals/vars в for петли в Словаре понимании:

>>> {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} 
Смежные вопросы