1.函數的引用
>>> def test():
print('test:')
>>> test
<function test at 0x10ffad488>
>>> myfun=test
>>> myfun()
test:
>>>
函數名實際上指向函數體的內存區域,因此輸出函數名時爲:
<function test at 0x10ffad488>
若myfun=test,此時
變量 myfun 也指向了該內存區域,因此能夠經過 test() 調用函數,也能夠經過 myfun() 調用
這種狀況,在C 、C++中相似 函數指針
2.什麼是閉包?
在函數內部定義一個函數,而且這個函數用到外邊函數的變量,這個函數以及用到的變量
統稱爲閉包
如:
>>> def test(number):
print('---1---')
def test_in():
print(number+100)
print('---2---')
print('---3---')
return test_in()
>>> test(2)
---1---
---3---
102
---2---
>>>
定義一個函數 test() ,在函數內部定義另外一個函數 test_in()
test_in()又使用到了 外部函數 的變量,此時,test_in()和
被使用到的變量,統稱爲閉包
>>> def test(number):
print('---1---') # 1
def test_in(): #2 只定義 「內」函數 沒被執行
print(number+100)
print('---2---')
print('---3---') #3
return test_in() #4 在return 語句,調用「內」函數
3.閉包的應用
如:
>>> def test(number):
def test_in():
print(number+100)
return test_in
>>> ref=test(11)
>>> ref()
111
>>>
在 外部函數 內定義了 內部函數, 內部函數又使用了 內部函數的變量
外部函數返回了內部函數的地址:
return test_in
此時 ref=test(11) ,使得ref獲得了 test_in()的引用
因而能夠經過 ref() 直接調用函數,雖然test_in使用了外部函數test()的變量number
但接下來每次調用ref() 均可以直接調用,
外部函數變量number不被釋放
>>> ref() # ref() 儼然如同一個獨立函數了
111
>>> ref()
111
>>> ref()
111
>>>
4.外邊函數被保留
外部函數雖然只調用了一次,但它不能被銷燬,緣由是內部函數還須要使用到它的變量,若該函數被銷燬,則內邊函數將沒法被正常調用
ref() 之因此可以被反覆調用,一方面在於調用外部函數test()時將test_in()的地址賦值給ref變量,這隻讓ref指向了函數體,可以以ref()的方式被調用,
而另外一方面,當內部函數體被調用時,不可以出錯,因此須要保留它須要用到的外部變量,
所以number變量必須存在,test函數就必須保留。
閉包的一個特色:外部函數返回 內部函數的一個引用
5.閉包的一個應用實例:
>>> def test(a,b):
def test_in(x):
print(a*x+b)
return test_in
'''
在調用test時,傳遞了a,b;實際上直線已經被肯定,因此如下
line1和line2中直接傳個值就能夠了。
'''
>>> line1=test(2,5)
>>> line1(1)
7
>>> line2=test(3,4)
>>> line2(2)
10
>>>
在這個例子中,
函數test_in和變量a,b構成閉包。
咱們只須要經過變換a,b的值,就能夠肯定一條不一樣的直線(y=2x+5 / y=3x+4)
由此,
閉包具有提升代碼複用性的做用
若是沒有閉包,咱們須要每次建立直線函數時,同時說明a,b,x,這樣須要更多的函數傳遞
並且減小了代碼的可移植性:
>>> def line(a,b,x):
print(a*x+b)
>>> line(1,1,1)
2
>>> line(2,2,2)
6
>>>
每次都須要傳遞a,b,x的值,而使用閉包的話,a,b能夠只寫一次,讓調用過程簡化
6.如圖:從新開闢空間
Python解釋器在處理閉包時,因爲line1=test(1,1) 調用了test,此時test沒有被釋放,依然佔用着內存;
在處理line2=test(2,2)時,不會覆蓋到原先執行line1=test(1,1)時test的內存,也就是說不會改變
原先a=1,b=1的test,而是會新申請一塊內存,執行「新」test,再保存a=2,b=2
7.閉包的思考
1.優化了變量
2.因爲閉包引用了外部函數的變量,
外部函數的局部變量沒有被及時釋放,消耗內存。