6 个相似问题求个合理的分析

2019-05-14 00:08:33 +08:00
 chinesehuazhou

下面有 6 个例子,都挺相似,但结果比较费解。求一个能够完整解释 6 个例子的分析。

# 例 0
def foo():
    exec('y = 1 + 1')
    z = locals()['y']
    print(z)
    
foo()

# 输出:2
# 例 1
def foo():
    exec('y = 1 + 1')
    y = locals()['y']
    print(y)
    
foo()

# 报错:KeyError: 'y'
# 例 2
def foo():
    y = 1 + 1
    y = locals()['y']
    print(y)

foo()

# 2
# 例 3
def foo():
    exec('y = 1 + 1')
    boc = locals()
    y = boc['y']
    print(y)
 
foo()

# KeyError: 'y'
# 例 4
def foo():
    boc = locals()
    exec('y = 1 + 1')
    y = boc['y']
    print(y)

foo()

# 2
# 例 5
def foo():
    boc = locals()
    exec('y = 1 + 1')
    print(locals())
    y = boc['y']
    print(y)

foo()

# KeyError: 'y'
{'boc': {...}}
1374 次点击
所在节点    Python
4 条回复
so1n
2019-05-14 13:01:41 +08:00
作用域问题,定义与声明混乱了,查看字节码能看得出区别
ec0
2019-05-14 13:42:47 +08:00
事实 1:locals() dict 是局部变量空间的拷贝, 不等于 局部变量空间

猜想 1:exec('y = 1 + 1') 相当于 locals()['y'] = 2

猜想 2 : 调用 locals() 会刷新对应的 dict 对象(与局部变量空间同步),把定义并赋值的局部变量加入 locals() dict,把定义但未赋值的局部变量从 locals() dict 中清除

例 5:
print(locals()) 第二次调用了 locals() ,根据猜想 2,locals() dict 和局部变量空间同步,而局部变量空间里,y 已经定义但是没有赋值,locals() dict 会清除 y,所以 KeyError

例 4:
boc = locals() 调用 locals() ,locals()['y'] = 2 后,没有再次调用 locals() ,locals()['y'] 得以保留

例 3:
locals()['y'] = 2 之后调用了 locals() ,locals () dict 刷新,KeyError

例 2:
y = 1+1,y 已定义并赋值,locals() dict 有 key y,输出 2

例 1:
locals()['y'] = 2 后,y = locals()['y'] 调用了 locals() ,刷新 locals() dict,KeyError

例 0:
locals()['y'] = 2 后执行 z = locals()['y'] ,调用了 locals() ,刷新 locals() dict,刷新以后仍然可以输出 2,所以有了猜想 3

猜想 3:在刷新 locals() dict 时,如果一个 key 不是局部变量,那么刷新时得以保留


参考:
[为什么 Python 里面的 locals()是只读的]( https://zhuanlan.zhihu.com/p/21815224)
chinesehuazhou
2019-05-17 21:46:34 +08:00
@ec0 谢谢解答,不过我还是觉得不够全面,详细地写了一篇文章,欢迎交流: https://neue.v2ex.com/t/565190
chinesehuazhou
2019-05-17 21:48:32 +08:00
@ec0 主要是例 5 的 print 结果,循环引用不应该忽视

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/563837

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX