Python:dict 理解和 eval 函数变量范围

Python:dict comprehension and eval function variable scope

代码 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:听写理解

def foo():
    one = '1'
    two = '2'
    three = '3'
    print({name: eval(name) for name in ('one', 'two', 'three')})

foo()

输出:

NameError: name 'one' is not defined

代码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为什么不能访问外层函数foo的变量one[,two,three]呢?但是代码3通过设置变量one[,two,three]为global?

可以成功创建字典

所以是因为 eval 函数和 dict comprehensions 有不同的作用域吗?

希望有人帮助我,我将不胜感激!

要了解发生了什么,试试这个:

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() 不是函数的局部符号 table,因为 list/dict 理解有其自己的范围(例如,参见 https://bugs.python.org/msg348274 ).

要获得预期的输出,只需将函数的局部符号 table 传递给 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'}