以下是代码:
以上代码输出:
def caller(callee):
callee()
def wrapper():
def a():
print v0
for i in range(5):
v0 = i*i
caller(a)
wrapper()
但我不明白0
1
4
9
16
如何解析变量a
。我找不到有关此语言功能的相关python文档。
答案 0 :(得分:2)
函数中定义的变量范围包括其中的所有嵌套函数。因此wrapper()
中定义的变量可以在a()
中访问,因为此函数嵌套在其中。这被称为词法范围,它通常用于创建闭包。
Python Resolution of Names文档中对此进行了解释:
范围定义块中名称的可见性。如果在块中定义了局部变量,则其范围包括该块。如果定义发生在功能块中,则范围将扩展到定义块中包含的任何块,除非包含的块为名称引入了不同的绑定。
答案 1 :(得分:1)
每次调用a
时都会定义函数wrapper
。当调用a
的给定实例时,它会在其定义的上下文中查找v0
,这是对定义它的wrapper
的特定调用。在调用a
时,v0
已在wrapper
内定义,a
使用v0
的定义。
在此示例中,调用wrapper
时,定义a
的{{1}}的调用仍处于活动状态,但不一定如此。换句话说,a
可以返回,并且仍然可以调用对该上下文的wrapper
的引用。在这种情况下,它将是一个闭包。但是在这个例子中不会发生这种情况。
这是一个使用闭包的示例:
a
输出结果为:
def foo(x):
def bar():
return x
return bar
f1 = foo(123)
f2 = foo(456)
print(f1())
print(f2())
调用123
456
时,它会返回foo
的实例,该实例在调用bar
的上下文中评估x
。在第一次调用中,foo
为123,在第二次调用中为x
。即使在调用456
之后,这些绑定仍然存在。
答案 2 :(得分:0)
请记住,在调用函数之前,函数中的所有代码都不会运行。在调用a()
时,v0
已在外部范围中定义,因此它可以识别变量并对其进行评估。