赞
踩
在 Python 中,闭包(closure)是一个常见的编程技巧。闭包是指一个函数对象,该函数能够访问其定义域外部的非全局变量,即使这些变量在函数调用时不处于活动状态也可以被访问。
def outer_func(x):
def inner_func(y):
return x + y
return inner_func
closure = outer_func(10)
print(closure(5)) # 输出:15
闭包的一个常见应用场景是实现装饰器(decorator)。装饰器本质上就是一个闭包,它用于修改另一个函数的行为。
在 Python 中,闭包不能直接修改外部函数的局部变量是因为,在 Python 闭包的实现方式中,内部函数能够访问外部函数的变量是基于“引用”,而不是基于“值传递”的。具体来说,当一个函数被定义时,其内部函数可以访问该函数所有的局部变量,包括那些已经超出了作用域的变量,这就形成了闭包。而当内部函数引用外部函数的变量时,实际上它引用的是该变量所在的内存地址,而不是变量本身的值。
因此,如果在闭包内部尝试直接修改外部函数的局部变量,则会导致该变量的内存地址发生变化,相当于创建了一个新的对象,而不是改变原有对象的值。
def outer_func2(): x = 0 print("----outer_func2---") def inner_func(): x = 1 # x的内存地址发生了变化,修改外部变量失败 print(f"inner_func中 x={x}") # 1 print(f"inner_func执行前 x={x}") # 0 inner_func() print(f"inner_func执行后 x={x}") # 0 def outer_func3(): x = [1,2,3] print("----outer_func3---") def inner_func(): x[0] = 444 # x的内存地址没有发送变化,修改外部变量成功 print(f"inner_func中 x={x}") # [444,2,3] print(f"inner_func执行前 x={x}") # [1,2,3] inner_func() print(f"inner_func执行后 x={x}") # [444,2,3]
如果要修改外部函数的局部变量,可以使用 nonlocal
关键字来通知 Python 解释器,让其知道需要修改的是外部函数的局部变量,而不是创建一个新的局部变量。
注:这种写法只适用于 Python 3,对于 Python 2.x 版本则无法直接修改外部函数的局部变量。
def outer_func4():
x = 0
print("----outer_func4---")
def inner_func():
nonlocal x
x = 1
print(f"inner_func中 x={x}") # 1
print(f"inner_func执行前 x={x}") # 0
inner_func()
print(f"inner_func执行后 x={x}") # 1
# 闭包的一个常见应用场景是实现装饰器 def outer_func(x): def inner_func(y): return x + y return inner_func def maintest1(): closure = outer_func(10) print(closure(5)) # 输出:15 # 闭包不能直接修改外部函数的局部变量 def outer_func2(): x = 0 print("----outer_func2---") def inner_func(): x = 1 print(f"inner_func中 x={x}") print(f"inner_func执行前 x={x}") inner_func() print(f"inner_func执行后 x={x}") def outer_func3(): x = [1,2,3] print("----outer_func3---") def inner_func(): x[0] = 444 print(f"inner_func中 x={x}") print(f"inner_func执行前 x={x}") inner_func() print(f"inner_func执行后 x={x}") def outer_func4(): x = 0 print("----outer_func4---") def inner_func(): nonlocal x x = 1 print(f"inner_func中 x={x}") print(f"inner_func执行前 x={x}") inner_func() print(f"inner_func执行后 x={x}") def maintest2(): outer_func2() outer_func3() outer_func4() if __name__=='__main__': maintest2() # maintest1()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。