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