Skip to main content
 首页 » 编程设计

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

2025年05月04日12jirigala

为什么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 的调用在一个单独的命名空间中>.