局部范围,超出了包围的范围 [英] Local scope, beyond the scope of the enclosing
问题描述
为什么lambda函数获取值列表i = 4。在调用lambda时,封闭范围不存在。函数f已完成工作和返回控制(变量i不存在)。
def f():
L = []
for i in range(5):
L.append(lambda x:i ** x)
return L
L = f()
L [0]
def f1(N):
def f2(X):
return X ** N
return f2
f = f1(2)
f )
9
g = f1(3)
g(3)
27
f(3)
9
Python使用 closures 捕获对原始变量的引用。 lambda
对象保留对 i
名称的引用,通过该名称可以访问该值。这意味着 i
变量在 f
完成后继续生效。
您可以在lambda对象上的 .__ closure __
tuple中内省这个闭包;函数具有相同的属性:
>> L [0] .__ closure__
(< cell on 0x1077f8b78:int object at 0x107465880> ;,)
>>> L [0] .__ closure __ [0]
< cell at 0x1077f8b78:int object at 0x107465880>
>>>> L [0] .__ closure __ [0] .cell_contents
4
em> all lambdas L
是指值 4
,而不是数字0
>>> L [0] .__ closure __ [0] is L [1] .__ closure __ [0]
True
闭包是指 变量,而不是定义闭包时该变量的值。在循环结束 i
最后设置为 4
,所以当查找 i
>如果你想让你的lambdas在循环中引用 i
的值,用一个关键字参数捕获它:
<范围(5)中的i:pre>
def f():
L = []
。 :i ** x)
return L
现在 i
是lambda的局部变量,而不是闭包。
或者,创建一个新的作用域来绘制闭包:
def create_lambda(i):
return lambda x:i ** x
def f ):
return [create_lambda(i)for i in range(5)]
create_lambda()
是一个新的作用域,它有自己的局部 i
用于lambda闭锁。然后每个lambdas都有自己的闭包:
>>> L [0] .__ closure __ [0] is L [1] .__ closure __ [0]
False
闭包是指特定命名空间中的变量;每次调用函数时,都会创建一个新的本地命名空间,因此每个闭包都会单独引用 i
中的 create_lambda
命名空间与其他调用 create_lambda
。
Why lambda function to get the list of values i = 4 .During the call lambda, enclosing scope does not exist. The function f has finished work and returned control (the variable i does not exist).
def f():
L = []
for i in range(5):
L.append(lambda x: i ** x)
return L
L = f()
L[0]
def f1(N):
def f2(X):
return X**N
return f2
f=f1(2)
f (3)
9
g = f1(3)
g(3)
27
f(3)
9
Python uses closures to capture references to the original variable. The lambda
objects retain a reference to the i
name, through which the value can be accessed. This means that the i
variable continues to live on after f
completes.
You can introspect this closure in the .__closure__
tuple on the lambda objects; functions have the same attribute:
>>> L[0].__closure__
(<cell at 0x1077f8b78: int object at 0x107465880>,)
>>> L[0].__closure__[0]
<cell at 0x1077f8b78: int object at 0x107465880>
>>> L[0].__closure__[0].cell_contents
4
This is also why all lambdas in your list L
refer to the value 4
, and not to the numbers 0 through to 4. They all refer to the same closure:
>>> L[0].__closure__[0] is L[1].__closure__[0]
True
The closure refers to the variable, not to the value of that variable at the time the closure was defined. At the end of the loop i
was last set to 4
, so when looking up i
in the lambda closure 4
will be found, for all lambdas in your list.
If you want your lambdas to refer to the value of i
during the loop, capture it in a keyword argument:
def f():
L = []
for i in range(5):
L.append(lambda x, i=i: i ** x)
return L
Now i
is a local variable to the lambda, not a closure.
Alternatively, create an entirely new scope from which to draw the closure:
def create_lambda(i):
return lambda x: i ** x
def f():
return [create_lambda(i) for i in range(5)]
Now create_lambda()
is a new scope with it's own local i
for the lambda closure to refer to. The lambdas then each have their own closures:
>>> L[0].__closure__[0] is L[1].__closure__[0]
False
Closures refer to a variable in a specific namespace; each time you call a function a new local namespace is created, so each closure refers to i
in create_lambda
in a separate namespace from other calls to create_lambda
.
这篇关于局部范围,超出了包围的范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!