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

时间:2020-06-05 05:28:46

标签: python-3.x scope global-variables dictionary-comprehension

代码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理解具有不同的范围吗?

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

1 个答案:

答案 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'}