2015-06-24 14 views
12

Tôi có đoạn như sau:Python: vấn đề khi sử dụng VAR() từ điển

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

nào mang lại cho tôi KeyError: 'a' trong khi đoạn mã sau hoạt động tốt:

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

sự khác biệt ở đây là gì?

+2

Bạn đang yêu cầu bởi vì bạn đang tò mò, không phải vì bạn dựa vào 'vars() '/' người dân địa phương() 'trong các chương trình thực tế của bạn, phải không? – TigerhawkT3

+0

@ TigerhawkT3: bây giờ sau khi bạn đã hỏi tôi muốn nói chỉ vì tò mò :) – Ulysses

Trả lời

9

vars() mà không có bất kỳ đối số nào hoạt động như locals() và vì từ điển hiểu có phạm vi riêng của nó, không có biến có tên a hoặc b.

Bạn có thể sử dụng eval() tại đây. Nếu không có bất kỳ tranh luận nó sẽ thực hiện trong LEGB cách, hoặc chỉ định globals() dict rõ ràng để eval:

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

Nhưng sau đó một lần nữa đúng cách sẽ tạo ra một từ điển từ đầu nếu bạn muốn truy cập các biến sử dụng tên của họ.

+0

Điều gì sẽ là cách để sửa chữa nó nếu tôi không muốn đi qua một vòng lặp nhiều dòng? – Ulysses

+3

Cách tốt nhất để khắc phục nó là tránh lộn xộn với 'vars()'/'locals()' hoàn toàn, bởi vì chúng sẽ cung cấp cho bạn các vấn đề như thế này. – TigerhawkT3

+1

Tôi chỉ sử dụng 'vars()' với 'định dạng': nó chỉ là quá hấp dẫn để viết' 'foo {bar} baz {spam}' định dạng (** vars()) 'chứ không phải là' .format (bar = bar , spam = spam) '.Nhưng nó đi sai trong một sự hiểu biết. @ TigerhawkT3 những gì bạn sẽ khuyên bạn nên thay thế Pythonic vào '.format (** vars())' mã của tôi? – gerrit

5

của nó vì lý do đó trong mã của bạn vars trả về một cuốn từ điển chứa địa phương variables.actually dựa trên tài liệu:

Nếu không có một cuộc tranh cãi, vars() hành vi như locals().

xem ví dụ sau:

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

Như bạn có thể thấy chúng tôi không có bất kỳ biến địa phương trong phạm vi chức năng a nên vars lợi nhuận một từ điển rỗng.

Và trong trường hợp của bạn như là một cách pythonic hơn bạn có thể tạo một từ điển của các đối tượng của bạn:

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

Dường như Python làm cho một đóng cửa trong sự hiểu biết từ điển (nói, dictcomp)

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

Sử dụng vars() trong vòng lặp for thực hiện dưới dạng mã thứ hai bạn đã cung cấp.

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

Chúng ta có thể tìm ra các mới locals/vars trong for vòng lặp trong dict hiểu:

>>> {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} 
Các vấn đề liên quan