gpt4 book ai didi

python - 什么时候检查非局部变量的存在?

转载 作者:太空狗 更新时间:2023-10-29 18:32:09 25 4
gpt4 key购买 nike

我正在学习 Python,现在我正在学习作用域和非局部语句的主题。在某个时候,我以为我已经弄明白了,但是 nonlocal 来了,把一切都搞砸了。

示例编号 1:

print( "let's begin" )
def a():
def b():
nonlocal x
x = 20
b()

a()

运行自然失败。
更有趣的是 print() 没有被执行。为什么?

我的理解是封闭的def a()直到print()被执行,嵌套的def b()是仅在调用 a() 时执行。我很困惑...

好的,让我们尝试示例 2:

print( "let's begin" )
def a():
if False: x = 10
def b():
nonlocal x
x = 20
b()

a()

Aaand... 它运行良好。什么?!那是怎么解决的?函数 a 中的 x = 10 永远不会执行!

我的理解是非本地语句在运行时被评估和执行,搜索封闭函数的调用上下文并将本地名称 x 绑定(bind)到某个特定的“外部”x。如果外部函数中没有 x - 引发异常。同样,在运行时。

但现在看起来这是在语法分析时完成的,非常愚蠢的检查“查看 x = blah 的外部函数,如果有这样的事情 - 我们很好,"即使那个 x = blah 永远不会被执行...

任何人都可以向我解释何时以及如何处理非本地语句吗?

最佳答案

您可以看到 b 的作用域对 a 作用域中的自由变量(可用于绑定(bind))了解多少,如下所示:

import inspect

print( "let's begin" )

def a():
if False:
x = 10

def b():
print(inspect.currentframe().f_code.co_freevars)
nonlocal x
x = 20

b()

a()

给出:

let's begin
('x',)

如果您注释掉 nonlocal 行,并删除带有 xif 语句,您将看到可用的自由变量b 只是 ()

因此,让我们通过将 a 的定义放入 IPython 然后使用 dis.dis 来查看它生成的字节码指令:

In [3]: import dis

In [4]: dis.dis(a)
5 0 LOAD_CLOSURE 0 (x)
2 BUILD_TUPLE 1
4 LOAD_CONST 1 (<code object b at 0x7efceaa256f0, file "<ipython-input-1-20ba94fb8214>", line 5>)
6 LOAD_CONST 2 ('a.<locals>.b')
8 MAKE_FUNCTION 8
10 STORE_FAST 0 (b)

10 12 LOAD_FAST 0 (b)
14 CALL_FUNCTION 0
16 POP_TOP
18 LOAD_CONST 0 (None)
20 RETURN_VALUE

那么让我们看看how LOAD_CLOSURE is processed in ceval.c .

TARGET(LOAD_CLOSURE) {
PyObject *cell = freevars[oparg];
Py_INCREF(cell);
PUSH(cell);
DISPATCH();
}

所以我们看到它必须从封闭范围的 freevars 中查找 x

这里提到in the Execution Model documentation ,它说:

The nonlocal statement causes corresponding names to refer to previously bound variables in the nearest enclosing function scope. SyntaxError is raised at compile time if the given name does not exist in any enclosing function scope.

关于python - 什么时候检查非局部变量的存在?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47814787/

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