gpt4 book ai didi

python - 局部范围,超出封闭范围

转载 作者:太空宇宙 更新时间:2023-11-04 07:09:52 25 4
gpt4 key购买 nike

为什么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 (3)
9
g = f1(3)
g(3)
27
f(3)
9

最佳答案

Python 使用 closures捕获对原始变量的引用。 lambda 对象保留对 i 名称的引用,通过它可以访问值。这意味着 i 变量在 f 完成后继续存在。

您可以在 lambda 对象的 .__closure__ 元组中检查这个闭包;函数具有相同的属性:

>>> 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

这也是为什么列表 L 中的所有 lambda 都引用值 4,而不是数字 0 到 4。它们都引用相同的闭包:

>>> L[0].__closure__[0] is L[1].__closure__[0]
True

闭包引用变量,而不是定义闭包时该变量的值。在循环结束时,i 最后设置为 4,因此在 lambda 闭包 4 中查找 i 时> 将被找到,对于您列表中的所有 lambda。

如果您希望 lambda 在循环期间引用 i 的值,请将其捕获在关键字参数中:

def f():
L = []
for i in range(5):
L.append(lambda x, i=i: 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 闭包引用。然后每个 lambda 都有自己的闭包:

>>> L[0].__closure__[0] is L[1].__closure__[0]
False

闭包引用特定命名空间中的变量;每次调用一个函数时,都会创建一个新的本地命名空间,因此每个闭包都引用 create_lambda 中的 i,与其他对 create_lambda 的调用在一个单独的命名空间中>.

关于python - 局部范围,超出封闭范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17167764/

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