I have a list of variable names, like this:
我有一个变量名列表,如下所示:
['foo', 'bar', 'baz']
(I originally asked how I convert a list of variables. See Greg Hewgill's answer below.)
(我最初问过如何转换变量列表。请参阅下面的Greg Hewgill的答案。)
How do I convert this to a dictionary where the keys are the variable names (as strings) and the values are the values of the variables?
如何将其转换为字符,其中键是变量名称(作为字符串),值是变量的值?
{'foo': foo, 'bar': bar, 'baz': baz}
Now that I'm re-asking the question, I came up with:
现在我正在重新提出这个问题,我想出了:
d = {}
for name in list_of_variable_names:
d[name] = eval(name)
Can that be improved upon?
可以改进吗?
Update, responding to the question (in a comment) of why I'd want to do this:
更新,回答问题(在评论中)为什么我想这样做:
I often find myself using the % operator to strings with a dictionary of names and values to interpolate. Often the names in the string is just the names of local variables. So (with the answer below) I can do something like this:
我经常发现自己使用%运算符来为字符串添加要插入的名称和值的字典。通常,字符串中的名称只是局部变量的名称。所以(下面的答案)我可以做这样的事情:
message = '''Name: %(name)s
ZIP: %(zip)s
Dear %(name)s,
...''' % dict((x, locals()[x]) for x in ['name', 'zip'])
4 个解决方案
#1
15
Forget filtering locals()
! The dictionary you give to the formatting string is allowed to contain unused keys:
忘记过滤本地人()!您为格式化字符串提供的字典允许包含未使用的键:
>>> name = 'foo'
>>> zip = 123
>>> unused = 'whoops!'
>>> locals()
{'name': 'foo', 'zip': 123, ... 'unused': 'whoops!', ...}
>>> '%(name)s %(zip)i' % locals()
'foo 123'
With the new f-string feature in Python 3.6, using locals()
is no longer necessary:
使用Python 3.6中的新f字符串功能,不再需要使用locals():
>>> name = 'foo'
>>> zip = 123
>>> unused = 'whoops!'
>>> f'{zip: >5} {name.upper()}'
' 123 FOO'
#2
4
Your original list [foo, bar, baz]
doesn't contain the variable names, it just contains elements that refer to the same values as the variables you listed. This is because you can have two different variable names that refer to the same value.
您的原始列表[foo,bar,baz]不包含变量名称,它只包含与您列出的变量引用相同值的元素。这是因为您可以使用两个不同的变量名来引用相同的值。
So, the list by itself doesn't contain information about what other names refer to the objects. The first element in your array has the name foo
but it also has the name a[0]
(assuming your array is called a
). After executing the following code, quux
also refers to the same object:
因此,列表本身不包含有关其他名称引用对象的信息。数组中的第一个元素名称为foo,但它的名称为[0](假设您的数组名为a)。执行以下代码后,quux也引用同一个对象:
quux = a[0]
Update: You're right that you can use eval()
for that, but its use is generally discouraged. Python provides a special member named __dict__
that contains the symbol table for the current module. So you can:
更新:您可以使用eval(),但通常不鼓励使用它。 Python提供了一个名为__dict__的特殊成员,它包含当前模块的符号表。所以你可以:
import __main__
d = dict((x, __main__.__dict__[x]) for x in list_of_variable_names)
Having to import __main__
when your code is in the unnamed main module is a quirk of Python.
当代码在未命名的主模块中时必须导入__main__是一个Python的怪癖。
#3
3
You can use list or generator comprehensions to build a list of key, value tuples used to directly instantiate a dict. The best way is below:
您可以使用list或generator comprehensions来构建用于直接实例化dict的键值元组列表。最好的方法如下:
dict((name, eval(name)) for name in list_of_variable_names)
In addition, if you know, for example, that the variables exist in the local symbol table you can save yourself from the dangerous eval by looking the variable directly from locals:
此外,如果您知道,例如,变量存在于本地符号表中,您可以通过直接从本地查找变量来保护自己免受危险的eval:
dict((name, locals()[name]) for name in list_of_variable_names)
After your final update, I think the answer below is really what you want. If you're just using this for string expansion with strings that you control, just pass locals() directly to the string expansion and it will cherry-pick out the desired values
在你最后的更新后,我认为下面的答案真的是你想要的。如果您只是使用它来控制字符串扩展,只需将locals()直接传递给字符串扩展,它将挑选出所需的值
If, however, these strings could ever come from an outside source (e.g. translation files), than it's a good idea to filter locals()
但是,如果这些字符串可能来自外部源(例如翻译文件),那么过滤本地人()是一个好主意()
#4
1
Not efficient, but without invoking eval
:
效率不高,但没有调用eval:
dict((k,v) for (k,v) in globals().iteritems() if k in list_of_variable_names)
or
dict((k,v) for (k,v) in vars().iteritems() if k in list_of_variable_names)
depending on what you want.
取决于你想要什么。
#1
15
Forget filtering locals()
! The dictionary you give to the formatting string is allowed to contain unused keys:
忘记过滤本地人()!您为格式化字符串提供的字典允许包含未使用的键:
>>> name = 'foo'
>>> zip = 123
>>> unused = 'whoops!'
>>> locals()
{'name': 'foo', 'zip': 123, ... 'unused': 'whoops!', ...}
>>> '%(name)s %(zip)i' % locals()
'foo 123'
With the new f-string feature in Python 3.6, using locals()
is no longer necessary:
使用Python 3.6中的新f字符串功能,不再需要使用locals():
>>> name = 'foo'
>>> zip = 123
>>> unused = 'whoops!'
>>> f'{zip: >5} {name.upper()}'
' 123 FOO'
#2
4
Your original list [foo, bar, baz]
doesn't contain the variable names, it just contains elements that refer to the same values as the variables you listed. This is because you can have two different variable names that refer to the same value.
您的原始列表[foo,bar,baz]不包含变量名称,它只包含与您列出的变量引用相同值的元素。这是因为您可以使用两个不同的变量名来引用相同的值。
So, the list by itself doesn't contain information about what other names refer to the objects. The first element in your array has the name foo
but it also has the name a[0]
(assuming your array is called a
). After executing the following code, quux
also refers to the same object:
因此,列表本身不包含有关其他名称引用对象的信息。数组中的第一个元素名称为foo,但它的名称为[0](假设您的数组名为a)。执行以下代码后,quux也引用同一个对象:
quux = a[0]
Update: You're right that you can use eval()
for that, but its use is generally discouraged. Python provides a special member named __dict__
that contains the symbol table for the current module. So you can:
更新:您可以使用eval(),但通常不鼓励使用它。 Python提供了一个名为__dict__的特殊成员,它包含当前模块的符号表。所以你可以:
import __main__
d = dict((x, __main__.__dict__[x]) for x in list_of_variable_names)
Having to import __main__
when your code is in the unnamed main module is a quirk of Python.
当代码在未命名的主模块中时必须导入__main__是一个Python的怪癖。
#3
3
You can use list or generator comprehensions to build a list of key, value tuples used to directly instantiate a dict. The best way is below:
您可以使用list或generator comprehensions来构建用于直接实例化dict的键值元组列表。最好的方法如下:
dict((name, eval(name)) for name in list_of_variable_names)
In addition, if you know, for example, that the variables exist in the local symbol table you can save yourself from the dangerous eval by looking the variable directly from locals:
此外,如果您知道,例如,变量存在于本地符号表中,您可以通过直接从本地查找变量来保护自己免受危险的eval:
dict((name, locals()[name]) for name in list_of_variable_names)
After your final update, I think the answer below is really what you want. If you're just using this for string expansion with strings that you control, just pass locals() directly to the string expansion and it will cherry-pick out the desired values
在你最后的更新后,我认为下面的答案真的是你想要的。如果您只是使用它来控制字符串扩展,只需将locals()直接传递给字符串扩展,它将挑选出所需的值
If, however, these strings could ever come from an outside source (e.g. translation files), than it's a good idea to filter locals()
但是,如果这些字符串可能来自外部源(例如翻译文件),那么过滤本地人()是一个好主意()
#4
1
Not efficient, but without invoking eval
:
效率不高,但没有调用eval:
dict((k,v) for (k,v) in globals().iteritems() if k in list_of_variable_names)
or
dict((k,v) for (k,v) in vars().iteritems() if k in list_of_variable_names)
depending on what you want.
取决于你想要什么。