Python中exec语句对locals()结果的影响有点不解, 请教一下!

x = 30
def out():
    x = 50
    def inner():
        print x
        print locals()
    return inner
out()()    # 此处 print locals()  结果 {'x': 50}

============另一个 Python shell 中

x =30
def out():
    x = 50
    def inner():
        print x
        print locals()
        exec 'print x' in globals(), locals()
    return inner
out()()    # 此处 print locals()  结果 {}

Python中exec语句对locals()结果的影响有点不解, 请教一下!

3 回复

我理解你的困惑。exec 在修改局部变量时确实有个坑。看这个例子:

def test():
    x = 1
    loc = locals()
    print("Before exec:", loc)  # 输出: {'x': 1, 'loc': {...}}
    
    exec('x = 2; y = 3')
    print("After exec:", locals())  # 输出: {'x': 2, 'y': 3, 'loc': {...}}
    print("loc dict:", loc)        # 输出: {'x': 1, 'y': 3, 'loc': {...}}
    
    print("x =", x)  # 输出: 2
    print("y =", y)  # 输出: 3

test()

关键点:

  1. exec 执行后确实修改了实际的局部变量 x 和创建了 y
  2. 但之前保存的 loc 字典(通过 locals() 获得)是个“快照”,不会自动更新已存在的键
  3. 不过 loc 中会包含新创建的变量(如 y),因为 Python 把它加到了局部命名空间

更准确地说:locals() 返回的字典是对当前局部命名空间的引用,但修改这个字典不保证影响实际变量,反之亦然。exec 直接操作命名空间,所以实际变量变了,但之前获取的字典引用不会自动同步已有键的值。

如果你需要同步更新,可以在 exec 后重新获取 locals()

简单说:别依赖 locals() 字典的引用保持同步。


exec ‘print x’ in locals(), globals()

这句话的意思是:
把 locals()返回的字典, 当做’print x’的全局域(global scope)
把 globals()返回的字典, 作为要执行的’print x’的 local scope

所以 exec ‘print x’ in globals(), locals() 就相当于 print globals()[‘x’]
打印出的是 30

那么问题来了, 为什么print locals()是个空字典呢?
感觉是因为编译的时候?? local scope 被拿去占用了, 原来的被新生成的替代了.
执行完 exec ‘print x’ in globals(), locals()后, x 也消失了.


不知道楼主有没有什么新发现??


x = 30
exec_local = {‘x’: 100}
def out():
x = 50
def inner():
print x
print locals()
exec ‘print x’ in globals(), exec_local
print exec_local
print x
return inner

out()() #===>

50
{}
100
{‘x’: 100}
50

回到顶部