python深入學習筆記4 閉包

2021-08-14 13:58:52 字數 2124 閱讀 6630

函式物件的作用域

函式物件的作用域與def所在層級相同。如:

def

line_conf

():def

line

(x):

return

2*x+1

print(line(5)) #在作用域範圍內

line_conf()

print(line(5)) #超出作用域了

閉包

函式是乙個物件,所以可以作為某一函式的返回結果。

def

line_conf

():def

line

(x):

return

2*x+1

return line

my_line=line_conf()

print(my_line(5)) #即呼叫了line(5)

輸出結果為11。

如果line()的定義中引用了外部的變數,會發生什麼呢?

def

line_conf

(): b=15

defline

(x):

return

2*x+b

return line

b=5my_line=line_conf()

print(my_line(5))

我們可以看到,line定義的隸屬程式塊中引用了高層級的變數b,但b資訊存在於line的定義之外 (b的定義並不在line的隸屬程式塊中)。我們稱b為line的環境變數。事實上,line作為line_conf的返回值時,line中已經包括b的取值(儘管b並不隸屬於line)。

上面的**將列印25,也就是說,line所參照的b值是函式物件定義時可供參考的b值,而不是使用時的b值。

乙個函式和它的環境變數合在一起,就構成了乙個閉包(closure)。在python中,所謂的閉包是乙個包含有環境變數取值的函式物件。環境變數取值被儲存在函式物件的__closure__屬性中。比如下面的**:

def

line_conf

(): b=15

defline

(x):

return

2*x+b

return line

b=5my_line=line_conf()

print(my_line.__closure__)

print(my_line.__closure__[0].cell_contents)

輸出:

(0x0000017972f786d8: int

object at 0x000000005527b600>,)

15

所有的函式物件都有乙個__closure__屬性,如果它是乙個閉包函式,那麼它包含乙個cell objects元組。cell object有cell_contents屬性,儲存了閉合數值。我們看到第乙個cell包含的就是整數15,也就是我們建立閉包時的環境變數b的取值。

下面看乙個閉包的實際例子:

def

line_conf

(a,b):

defline

(x):

return a*x+b

return line

line1=line_conf(1,1)

line2=line_conf(4,5)

print(line1(5),line2(5))

這個例子中,函式line與環境變數a,b構成閉包。在建立閉包的時候,我們通過line_conf的引數a,b說明了這兩個環境變數的取值,這樣,我們就確定了函式的最終形式(y = x + 1和y = 4x + 5)。我們只需要變換引數a,b,就可以獲得不同的直線表達函式。由此,我們可以看到,閉包也具有提高**可復用性的作用。

如果沒有閉包,我們需要每次建立直線函式的時候同時說明a,b,x。這樣,我們就需要更多的引數傳遞,也減少了**的可移植性。利用閉包,我們實際上建立了泛函。line函式定義一種廣泛意義的函式。這個函式的一些方面已經確定(必須是直線),但另一些方面(比如a和b引數待定)。隨後,我們根據line_conf傳遞來的引數,通過閉包的形式,將最終函式確定下來

Python深入學習之閉包

閉包 closure 是函式式程式設計的重要的語法結構。函式式程式設計是一種程式設計正規化 而面向過程程式設計和物件導向程式設計也都是程式設計正規化 在面向過程程式設計中,我們見到過函式 function 在物件導向程式設計中,我們見過物件 object 函式和物件的根本目的是以某種邏輯方式組織 並...

Python深入學習筆記(二)

計數器counter counter類是自python2.7起增加的,屬於字典類的子類,是乙個容器物件,主要用來統計雜湊物件,支援集合操作 其中後兩項分別返回兩個counter物件各元素的最小值和最大值。from collections import counter c counter succes...

gorrilla Context包深入學習

做過web開發的同學肯定都知道,我們經常使用r http.request這個變數來獲取我們希望獲得的引數,但是我們經常遇到這樣乙個場景,我們需要為我們的r設定更多的key value形式的附加值,一般我們都會儲存在乙個map物件中,用的時候再從裡面取出,golang考慮到這樣乙個場景,為我們提供了乙...