【问题标题】:Given a list of variable names in Python, how do I a create a dictionary with the variable names as keys (to the variables' values)?给定 Python 中的变量名列表,我如何创建一个以变量名作为键的字典(到变量的值)?
【发布时间】:2010-09-18 20:32:57
【问题描述】:

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

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

(我最初问我如何转换变量列表。请参阅下面 Greg Hewgill 的回答。)

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

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

现在我重新问这个问题,我想出了:

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

可以改进吗?

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

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

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

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

【问题讨论】:

  • 改装下来。我看不到你想要这样做的合理情况,而且我看不出有什么办法让它变得健壮,当然也不用 eval。如果名称列表的名称掩盖了感兴趣的名称之一,等等。
  • 您可以将 dict((x, locals()[...) 替换为 vars()
  • 示例:a, b = 1, 'astring'; print("%(a)s %(b)s %(b)r" % vars())

标签: python list dictionary


【解决方案1】:

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

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

使用 Python 3.6 中的新 f-string feature,不再需要使用 locals()

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

【讨论】:

  • 如果您使用 str.format() 方法,请这样做:'{name} {zip}'.format(**locals())
【解决方案2】:

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

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

此外,例如,如果您知道变量存在于本地符号表中,您可以通过直接从本地查看变量来避免危险的 eval:

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

在您最终更新之后,我认为下面的答案确实是您想要的。如果您只是将它用于您控制的字符串的字符串扩展,只需将 locals() 直接传递给字符串扩展,它就会挑选出所需的值

但是,如果这些字符串可能来自外部来源(例如翻译文件),那么过滤 locals() 是个好主意

【讨论】:

  • 由于字典中可能有未使用的键,您可以直接使用 "..." % locals() 而不过滤
  • 同意,"..." % locals() 也更加 Pythonic,因为它是一个常见的习语。
  • 我通过使用 dict([(name, locals()[name]) for name in list_of_variable_names]) 来实现这个功能
【解决方案3】:

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

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

quux = a[0]

更新:您可以使用 eval() 是对的,但通常不鼓励使用它。 Python 提供了一个名为 __dict__ 的特殊成员,其中包含当前模块的符号表。所以你可以:

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

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

【讨论】:

    【解决方案4】:

    效率不高,但没有调用eval

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

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

    取决于你想要什么。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-13
      • 1970-01-01
      • 1970-01-01
      • 2014-10-01
      • 1970-01-01
      • 2012-01-07
      相关资源
      最近更新 更多