首页 > 解决方案 > Python:dict理解和eval函数变量范围

问题描述

代码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()

输出:

NameError:名称“一”未定义

代码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'}

字典推导和生成器推导创建自己的本地范围。根据闭包的定义(或者这里不是闭包),但是为什么Code 2不能访问one[,two,three]外层函数的变量foo呢?one[,two,three]但是,代码3可以通过将变量设置为全局来成功创建字典吗?

那么是因为eval函数和字典理解有不同的范围吗?

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

标签: python-3.xscopeglobal-variablesdictionary-comprehension

解决方案


要了解发生了什么,请尝试以下操作:

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

推荐阅读