代码 1:for 循环
def foo():
one = '1'
two = '2'
three = '3'
d = {}
for name in ('one', 'two', 'three'):
d[name] = eval(name)
print(d)
foo()
输出:
{'一': '1', '二': '2', '三': '3'}
代码2:字典理解
def foo():
one = '1'
two = '2'
three = '3'
print({name: eval(name) for name in ('one', 'two', 'three')})
foo()
输出:
名称错误:未定义名称"一">
代码3:添加全局关键字
def foo():
global one, two, three # why?
one = '1'
two = '2'
three = '3'
print({name: eval(name) for name in ('one', 'two', 'three')})
foo()
输出:
{'一': '1', '二': '2', '三': '3'}
字典推导和生成器推导创建自己的局部范围。根据闭包的定义(或者这里不是闭包(,但为什么代码 2 无法访问外部函数foo
的变量one[,two,three]
?但是,Code 3 可以通过将变量one[,two,three]
设置为全局来成功创建字典吗?
那么是因为eval
函数和字典理解有不同的范围吗?
希望有人帮助我,我会感激不尽!
要了解发生了什么,请尝试以下操作:
def foo():
global one
one = '1'
two = '2'
print({'locals, global': (locals(), globals()) for _ in range(1)})
foo()
输出
{'locals, global': ({'_': 0, '.0': <range_iterator object at ...>},
{'__name__': '__main__', '__package__': None, ..., 'one': '1'})}
内置eval(expression)
是eval(expression[, globals[, locals]])
的快捷方式。
正如您在前面的输出中看到的,locals()
不是函数的本地符号表,因为列表/字典推导式有自己的作用域(例如,请参阅 https://bugs.python.org/msg348274(。
要获得预期的输出,您只需将函数的本地符号表传递给eval
。
def bar():
one = '1'
two = '2'
three = '3'
func_locals = locals() # bind the locals() here
print({name: eval(name, globals(), func_locals) for name in ('one', 'two', 'three')})
bar()
输出
{'one': '1', 'two': '2', 'three': '3'}