閉包(閉包=函式+環境變數)
阿新 • • 發佈:2018-12-21
擴充:
- 函數語言程式設計(淡化)
- 函式只是一段可執行的程式碼,不可以例項化,並不是物件
- 一切皆物件、python 另外一個函式的引數,傳遞到另外的函式裡;把一個函式當做是另一個函式的返回結果:
def a():
pass
print(type(a))
#>>><class 'function'>
步入正題:閉包=函式+環境變數(函式定義時候的環境變數,不能是全域性變數)
閉包是函數語言程式設計的一種
1、閉包的形式及使用
#閉包 def curve_pre(): b=25 def curve(x):#曲線 return b*x*x return curve #curve()在外部不可以直接呼叫 b=10 f=curve_pre() print(f.__closure__)#__closure__內建函式存放閉包的環境變數資訊,返回的是閉包 #>>>(<cell at 0x0261B750: int object at 0x6DF7BFC8>,) print(f.__closure__[0].cell_contents) #>>>25 輸出環境變數的值 f(2)#執行函式==>curve(2) print(f(2)) #>>>100 #不會因為全域性變數而輸出40,而是使用環境變數a=25
__closure__內建函式存放閉包的環境變數資訊,返回的是閉包
__closure__[0].cell_contents
#>>>25 輸出環境變數的值
輸出結果:
>>>
<class 'function'>
(<cell at 0x0261B750: int object at 0x6DF7BFC8>,)
25
100
延伸:單個函式f1(),a是全域性變數,f1()函式在找不到a的值的情況下會呼叫全域性變數a=10
a=10 def f1(x): return a*x*x f1(2) print(f1(2)) #>>>40
閉包的經典誤區:
例子:
def f2():
c=10
def f3():
c=20
print(c)#②2>>>20
print(c)#①1>>>10
f3()
print(c)#③3>>>10
f2()
輸出結果:
>>>10
20
10
改動判斷是不是閉包:
#改動判斷是不是閉包 def f2(): c=10 def f3(): #此時將被python認為是一個區域性變數 c=20 return c return f3 w=f2() print(w) print(w.__closure__) #在這裡這個屬性__closure__是沒有的
輸出:
>>><function f2.<locals>.f3 at 0x008AE030>
None
重點!!!:在這裡這個屬性__closure__是沒有的,其實因為c=20存在,它此時將被python認為是一個區域性變數,內部函式輸出的是區域性變數而不是環境變數,不滿足閉包的要求,所以實質上此時還不是一個閉包
再改進:
def f2():
c=10
def f3():
#此時內部函式中只是引用了c
d=20*c
return c
return f3
w=f2()
print(w)
print(w.__closure__)
輸出:
<function f4.<locals>.f5 at 0x08896E88>
(<cell at 0x0371FB10: int object at 0x6DF7BED8>,)
此時根據print(w.__closure__)返回的資訊(<cell at 0x0371FB10: int object at 0x6DF7BED8>,)得知是一個閉包
用閉包來解決一個問題:旅行者,每走一步加一,編寫函式得到當前的位置
1、非閉包形式解決:
origin=0
def go(stpe):
global origin
new_pos=origin+stpe
origin=new_pos
return new_pos
print(go(2))#>>>2
print(go(3))#>>>5
print(go(6))#>>>11
2、閉包形式解決:
origin1=0
def factory(pos):
def go1(stpe):
#強制宣告pos不是區域性變數
nonlocal pos
new_pos=pos+stpe
pos=new_pos
return new_pos
return go1
tourist=factory(origin1)
print(tourist(2))#>>>2
print(origin1)#>>>0
print(tourist.__closure__[0].cell_contents)#>>>2
print(tourist(3))#>>>5
print(origin1)#>>>0
print(tourist.__closure__[0].cell_contents)#>>>5
print(tourist(6))#>>>11
print(origin1)#>>>0
print(tourist.__closure__[0].cell_contents)#>>>11
輸出:
2
0
2
5
0
5
11
0
11