【发布时间】:2013-09-10 22:30:05
【问题描述】:
为什么在字典推导中使用eval 访问函数参数会失败?
ARGS1 = ('a1', 'b1')
def foo1(a1, b1):
return {arg:eval(arg) for arg in ARGS1}
print foo1("A1", "B1") # NameError: name 'a1' is not defined
列表理解中的相同内容很好:
ARGS2 = ('a2', 'b2')
def foo2(a2, b2):
return [eval(arg) for arg in ARGS2]
print foo2("A2", "B2") # OK, print: ['A2', 'B2']
没有函数也能很好地工作:
ARGS3 = ('a3', 'b3')
a3, b3 = ("A3", "B3")
print {arg:eval(arg) for arg in ARGS3} # OK, print: ['A3', 'B3']
或者如果定义了全局变量:
ARGS4 = ('a4', 'b4')
a4, b4 = ("A4", "B4")
def foo4():
return [eval(arg) for arg in ARGS4]
print foo4() # OK, print: ['A4', 'B4']
这看起来确实像一个错误,但也许我在这里遗漏了一些东西。
(已编辑以包含无函数和有全局变量的示例)
【问题讨论】:
-
这不是一个错误,但 Python 3 中的行为已更改为更加一致。
-
你的第一个例子是 not 一个 dict 理解,这只是一个
dict文字。{arg: eval(arg) for arg in ARGS}然而是。 -
+1 @MartijnPieters 的第一条评论。另一种说法是,如果这里 存在 一个错误,那么列表理解有问题(并且在 3.0 中已修复),而 dict 理解按预期工作。跨度>
-
附带说明,
eval妨碍了通常的名称查找规则(这意味着您实际上必须详细了解它们,并且经常解决它们,而不是只是相信它们像魔术一样工作)是您几乎不想使用eval的众多原因之一。如果您真的想这样做,请执行loc = locals(); return {arg: loc[arg] for arg in ARGS}之类的操作,这将使您获得适当的关闭,并且更安全,更明确和可读。
标签: python arguments closures dictionary-comprehension