给定Python中的变量名列表,如何创建一个以变量名为键(变量';值)的字典?

给定Python中的变量名列表,如何创建一个以变量名为键(变量';值)的字典?,python,list,dictionary,Python,List,Dictionary,我有一个变量名列表,如下所示: ['foo', 'bar', 'baz'] message = '''Name: %(name)s ZIP: %(zip)s Dear %(name)s, ...''' % dict((x, locals()[x]) for x in ['name', 'zip']) (我最初问如何转换变量列表。请参见下面格雷格·休吉尔的回答。) 如何将其转换为一个字典,其中键是变量名(作为字符串),值是变量的值 {'foo': foo, 'bar': bar, 'baz'

我有一个变量名列表,如下所示:

['foo', 'bar', 'baz']
message = '''Name: %(name)s
ZIP: %(zip)s

Dear %(name)s,
...''' % dict((x, locals()[x]) for x in ['name', 'zip'])
(我最初问如何转换变量列表。请参见下面格雷格·休吉尔的回答。)

如何将其转换为一个字典,其中键是变量名(作为字符串),值是变量的值

{'foo': foo, 'bar': bar, 'baz': baz}
现在我在问这个问题,我想到了:

d = {}
for name in list_of_variable_names:
    d[name] = eval(name)
这能改进吗

更新,回答我为什么要这样做的问题(在评论中):

我经常发现自己使用%运算符对字符串使用名称和值字典进行插值。字符串中的名称通常只是局部变量的名称。所以(根据下面的答案)我可以做这样的事情:

['foo', 'bar', 'baz']
message = '''Name: %(name)s
ZIP: %(zip)s

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

原始列表
[foo,bar,baz]
不包含变量名,它只包含引用与所列变量相同值的元素。这是因为可以有两个不同的变量名引用相同的值

因此,列表本身并不包含关于其他名称引用对象的信息。数组中的第一个元素名为
foo
,但它也名为
a[0]
(假设数组名为
a
)。执行以下代码后,
qux
也引用相同的对象:

quux = a[0]
更新:您可以使用
eval()
来实现这一点,这是对的,但通常不鼓励使用它。Python提供了一个名为的特殊成员,该成员包含当前模块的符号表。因此,您可以:

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

当您的代码位于未命名的主模块中时,必须导入主模块是Python的一个怪癖。

您可以使用列表或生成器理解来构建用于直接实例化dict的键、值元组列表。最佳方法如下:

dict((name, eval(name)) for name in list_of_variable_names)
此外,例如,如果您知道变量存在于本地符号表中,您可以通过直接从本地变量中查找变量来避免危险评估:

dict((name, locals()[name]) for name in list_of_variable_names)
在你最后一次更新之后,我想下面的答案就是你想要的。如果您只是使用它来对您控制的字符串进行字符串扩展,只需将locals()直接传递给字符串扩展,它就会挑选出所需的值


但是,如果这些字符串可能来自外部源(例如翻译文件),则最好过滤局部变量()

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


取决于你想要什么。

忘记过滤
locals()
!您为格式化字符串提供的字典允许包含未使用的键:

>>> name = 'foo'
>>> zip = 123
>>> unused = 'whoops!'
>>> locals()
{'name': 'foo', 'zip': 123, ... 'unused': 'whoops!', ...}
>>> '%(name)s %(zip)i' % locals()
'foo 123'
对于Python 3.6中的新版本,不再需要使用
locals()

>>> name = 'foo'
>>> zip = 123
>>> unused = 'whoops!'
>>> f'{zip: >5} {name.upper()}'
'  123 FOO'

默丁下来。我认为没有合理的情况下,你会想这样做,我认为没有办法使它强大,当然没有与eval。如果名称列表的名称掩盖了一个感兴趣的名称,等等,该怎么办?回答更新以回应我的评论:这样做的Python习惯用法(我不支持,但我见过使用过)是直接“string%locals()”。您可以用
vars()替换
dict((x,locals()[…)
.Example:
a,b=1,'astring';print(“%(a)s%(b)s%(b)r”%vars())
由于dict中可能有未使用的键,您可以只使用“…”%locals(),而不使用filteringAgreed,”…%locals()也更像python,因为这是一个常见的习惯用法。我使用dict([(name,locals()[name])来实现这一点对于列表(变量名称)中的名称,如果您使用str.format()方法,请执行以下操作:
'{name}{zip}.format(**locals())