1:闭包的定义
首先看下面代码:
def outer():
x = 100
def inner():
print(x)
return inner
ret = outer()
ret()
"""
输出:
100
"""
在上面代码中,对ret的调用本质上是运行了outer运行时,里面创建的inner函数;这能行得通是因为Python中函数和其他一切一样都是对象,所以函数可以作为其他函数的返回值传递回来。更重要的是里面的函数inner记住了外层函数outer中的局部变量x,尽管外层函数outer已经不处于激活状态。
这种代码行为我们称之为闭包,或者叫工厂函数。其特点是它能够记住外层作用域中的值,不管那些嵌套作用域是否还在内存中。
其写法为:在外层函数中声明一个变量. 在内层函数使用或者返回这个变量。
2:闭包的作用
a:记忆外层作用域中的值;
b:可以保护变量不被修改;
c:可以让一个变量常驻内存;
def outer():
x = 100
def inner():
print(x)
return inner
# print(outer.x) # AttributeError: 'function' object has no attribute 'x'
outer.x = 300
print(outer.x)
action = outer()
action()
print(outer.x)
"""
输出:
300
100
300
3:一简单的工厂函数(闭包)
def outer(N):
def inner(X):
return X**N
return inner
f2 = outer(2)
print(f2(2)) # 2 ** 2
print(f2(3)) # 3 ** 2
print(f2(4)) # 4 ** 2
f3 = outer(3)
print(f3(2)) # 2 ** 3
print(f3(3)) # 3 ** 3
print(f3(4)) # 4 ** 3
4:使用 nonlocal 修改外层作用域中的变量
不能修改外层作用域中的变量(如下):
def outer(start):
cnt = start
def inner(lable):
print(lable,cnt)
# cnt += 1 # 不能修改外层作用域中的变量
return inner
f1 = outer(10)
f1('f1')
f1('f1')
f2 = outer(10)
f2('f2')
f2('f2')
"""
f1 10
f1 10
f2 10
f2 10
"""
使用nonlocal :
def outer(start):
cnt = start
def inner(lable):
nonlocal cnt
print(lable,cnt)
cnt += 1
return inner
f1 = outer(10)
f1('f1')
f1('f1')
f2 = outer(10)
f2('f2')
f2('f2')
f3 = outer(100)
f3('f3')
f3('f3')
f1('f1')
f2('f2')
f3('f3')
"""
# cnt 在f1,f2,f3中是独立的
f1 10
f1 11
f2 10
f2 11
f3 100
f3 101
f1 12
f2 12
f3 102
"""