gpt4 book ai didi

python - exec 语句将 LOAD_GLOBAL 更改为 LOAD_NAME?

转载 作者:太空宇宙 更新时间:2023-11-04 03:55:43 24 4
gpt4 key购买 nike

学习中this answer ,令我惊讶的是,exec 有一个奇怪的行为;

>>> def f1():
... return x
...
>>> def f2():
... exec ""
... return x
...
>>> f1()
Traceback (most recent call last):
...
NameError: global name 'x' is not defined
>>> f2()
Traceback (most recent call last):
...
NameError: name 'x' is not defined
>>> x = 'bar'
>>> f1()
'bar'
>>> f2()
'bar'

显然,两者都返回一些全局值 x;但如果 f2() 稍作更改,则不是这样:

>>> def f2():
... exec "x = 'im local now'"
... return x
...
>>> f2()
'im local now'

f2 返回它自己的 x 的特殊副本,即使 f2 的主体中没有任何东西似乎会导致这种情况(没有分配给 x)。

我可以很容易地看出这是怎么发生的,exec 语句的存在将 LOAD_GLOBAL 字节码更改为 LOAD_NAME,类似静脉作为 yield 的存在将一个函数变成了一个生成器。

>>> dis.dis(f1)
2 0 LOAD_GLOBAL 0 (x)
3 RETURN_VALUE
>>> dis.dis(f2)
2 0 LOAD_CONST 1 ('')
3 LOAD_CONST 0 (None)
6 DUP_TOP
7 EXEC_STMT

3 8 LOAD_NAME 0 (x)
11 RETURN_VALUE

但我不明白的是为什么。这是记录在案的行为吗?这是cpython的实现细节吗? (它在 IronPython 中的工作方式相同,尽管 dis 模块不起作用)

最佳答案

想象一个更一般的情况:

def f(stuff):
exec(stuff)
return x

Python 显然必须在这里使用LOAD_NAME,因为它不知道stuff 中的代码是否会与x 混淆。 any exec() 的使用也是同样的情况,即使参数是常量 — Python 只是没有进行足够深入的分析来确定任何 >exec() 恰好是安全的。

(为什么它不应该进行这种分析也有一个很好的理由:它可以甚至分析任何程度的成功的唯一情况是 exec() 在常量参数上,这是没有意义的。如果提前完全知道参数,它应该只是普通代码!)

关于python - exec 语句将 LOAD_GLOBAL 更改为 LOAD_NAME?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18647851/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com