2008-10-23 10 views
13

Tôi có một danh sách các tên biến, như thế này:Đưa ra một danh sách các tên biến trong Python, làm cách nào để tạo một từ điển có tên biến là các khóa (cho các giá trị của biến)?

['foo', 'bar', 'baz'] 

(ban đầu tôi hỏi làm thế nào để chuyển đổi một danh sách các biến Xem câu trả lời Greg Hewgill của bên dưới..)

Làm thế nào để chuyển đổi này cho một người từ điển mà các phím là các tên biến (như các chuỗi) và các giá trị là các giá trị của các biến?

{'foo': foo, 'bar': bar, 'baz': baz} 

Bây giờ tôi lại đặt ra câu hỏi, tôi đã đưa ra:

d = {} 
for name in list_of_variable_names: 
    d[name] = eval(name) 

mà có thể được cải thiện khi?

Cập nhật, đáp ứng cho câu hỏi (trong một bình luận) về việc tại sao tôi muốn làm điều này:

Tôi thường thấy mình sử dụng toán tử% đến chuỗi với một cuốn từ điển tên và giá trị để suy . Thường thì các tên trong chuỗi chỉ là tên của các biến cục bộ. Vì vậy, (với câu trả lời dưới đây) tôi có thể làm một cái gì đó như thế này:

message = '''Name: %(name)s 
ZIP: %(zip)s 

Dear %(name)s, 
...''' % dict((x, locals()[x]) for x in ['name', 'zip']) 
+0

Sửa đổi. Tôi thấy không có tình huống hợp lý nơi bạn sẽ muốn làm điều đó, và tôi thấy không có cách nào để làm cho nó mạnh mẽ, và chắc chắn không phải với eval. Điều gì sẽ xảy ra nếu tên của danh sách tên che khuất một trong các tên quan tâm, v.v. – ddaa

+0

Trả lời để cập nhật theo nhận xét của tôi: Thành ngữ Python để làm điều đó (mà tôi không hỗ trợ, nhưng tôi đã thấy được sử dụng), là "string% locals()" trực tiếp. – ddaa

+1

Bạn có thể thay thế 'dict ((x, locals() [...)' chỉ bằng 'vars()' – jfs

Trả lời

14

Quên lọc locals()! Từ điển bạn cung cấp cho chuỗi định dạng được phép chứa các phím không sử dụng:

>>> name = 'foo' 
>>> zip = 123 
>>> unused = 'whoops!' 
>>> locals() 
{'name': 'foo', 'zip': 123, ... 'unused': 'whoops!', ...} 
>>> '%(name)s %(zip)i' % locals() 
'foo 123' 
+4

và nếu bạn đang sử dụng phương thức str.format() làm như sau: ''{name} {zip}' format (** locals())' – krupan

4

danh sách ban đầu của bạn [foo, bar, baz] không chứa biến tên, nó chỉ chứa các yếu tố tham khảo với cùng giá trị như các biến bạn đã liệt kê. Điều này là do bạn có thể có hai tên biến khác nhau tham chiếu đến cùng một giá trị.

Vì vậy, danh sách của chính nó không chứa thông tin về những tên khác đề cập đến các đối tượng. Phần tử đầu tiên trong mảng của bạn có tên là foo nhưng nó cũng có tên a[0] (giả sử mảng của bạn được gọi là a). Sau khi thực hiện đoạn mã sau, quux cũng đề cập đến cùng một đối tượng:

quux = a[0] 

Cập nhật: Bạn nói đúng mà bạn có thể sử dụng eval() cho rằng, nhưng việc sử dụng nó thường không được khuyến khích. Python cung cấp một thành viên đặc biệt có tên là __dict__ có chứa bảng biểu tượng cho mô-đun hiện tại. Vì vậy, bạn có thể:

import __main__ 
d = dict((x, __main__.__dict__[x]) for x in list_of_variable_names) 

Phải import __main__ khi mã của bạn là trong module chính vô danh là một điều không minh bạch của Python.

3

Bạn có thể sử dụng tính năng liệt kê danh sách hoặc trình tạo máy phát để xây dựng danh sách các bộ giá trị khóa, giá trị được sử dụng để khởi tạo trực tiếp một dict. Cách tốt nhất là dưới đây:

dict((name, eval(name)) for name in list_of_variable_names) 

Bên cạnh đó, nếu bạn đã biết, ví dụ, rằng các biến tồn tại trong bảng biểu tượng địa phương mà bạn có thể tiết kiệm cho mình từ eval nguy hiểm bằng cách nhìn biến trực tiếp từ người dân địa phương:

dict((name, locals()[name]) for name in list_of_variable_names) 

Sau lần cập nhật cuối cùng của bạn, tôi nghĩ câu trả lời dưới đây thực sự là những gì bạn muốn.Nếu bạn chỉ sử dụng tính năng này để mở rộng chuỗi bằng các chuỗi mà bạn kiểm soát, chỉ cần chuyển trực tiếp từ địa phương() đến chuỗi mở rộng và nó sẽ chọn ra các giá trị mong muốn

Nếu, tuy nhiên, các chuỗi này có thể đến từ một nguồn bên ngoài (ví dụ như các file bản dịch), hơn đó là một ý tưởng tốt để lọc người dân địa phương()

+0

vì có thể có các phím không sử dụng trong dict, bạn chỉ có thể sử dụng "..."% locals() mà không lọc – hop

+0

Đồng ý, "..." – ephemient

+0

Tôi đã làm việc này bằng cách sử dụng dict ([(tên, người dân địa phương() [tên]) cho tên trong list_of_variable_names]) – pheon

1

Không hiệu quả, nhưng không có cách gọi eval:

dict((k,v) for (k,v) in globals().iteritems() if k in list_of_variable_names) 

hoặc

dict((k,v) for (k,v) in vars().iteritems() if k in list_of_variable_names) 

tùy thuộc vào những gì bạn muốn.