代码1:for循环
def foo():
one = '1'
two = '2'
three = '3'
d = {}
for name in ('one', 'two', 'three'):
d[name] = eval(name)
print(d)
foo()
输出:
{'one':'1','two':'2','three':'3'}
代码2:dict理解
def foo():
one = '1'
two = '2'
three = '3'
print({name: eval(name) for name in ('one', 'two', 'three')})
foo()
输出:
NameError:名称“ one”未定义
代码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()
输出:
{'one':'1','two':'2','three':'3'}
词典理解和生成器理解创建自己的局部作用域。根据闭包(或此处的闭包)的定义,但是代码2为什么不能访问外部函数one[,two,three]
的变量foo
?但是,代码3可以通过将变量one[,two,three]
设置为global来成功创建字典。
是因为eval
函数和dict理解具有不同的范围吗?
希望有人帮助我,我将不胜感激!
答案 0 :(得分:1)
要了解发生了什么,请尝试以下操作:
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'}