python閉包closure

在討論閉包以前,先總結一下python的命名空間namespace,通常的語言都是經過namespace來識別名字標識,不管是變量,對象,函數等等。python劃分3個名字空間層次,local:局部,標識爲當前函數內,當前類內,好比局部變量。global:全局,標識當前模塊,也就是當前文件,好比全局變量等。最後一類 built-in,內建,這個是做用域比較大,跨模塊(文件)均可以標識,好比咱們自建的文件中,引用內建函數dir(), 這就是一個典型的例子,自建的文件中可以並無聲明dir(),但因爲dir()是built_in內建函數,故在全部文件或模塊均可以引用。python

再來討論閉包:百度上對閉包的定義是:閉包是指能夠包含自由變量的代碼塊。定義簡單明瞭,也有把自由變量成爲環境變量的。緊接着定義什麼是自由變量或環境變量:這些變量不是在這個代碼塊內或者任何全局上下文中定義的,而是在定義代碼塊的環境中定義(局部變量)。結合namespace的概念,自由變量的位置:既不在函數local範圍內,也不在全局global範圍內,而是在兩個函數的做用域之間。舉個例子:c++

 1 def numFunc(a, b):
 2     num = 100
 3     num2 = 200
 4     num3 = 300
 5     print('print s in numbunc', s)
 6 
 7     def addfunc(a, b):
 8         s = 'string in addfunc'
 9         x = num
10         y = num3
11         print('print s in addFunc', s)
12 
13     return addfunc

num, num2, num3, 這三個變量符合自由變量的描述,既不在局部local內,也再也不全局global內。而是在兩個函數的做用域之間。閉包

因此我們說白了,閉包從形式上說,就是函數內嵌一個函數。可是還需知足兩個條件,1.內層函數引用環境變量(自由變量)2外部函數返值爲內部函數名(一個返回函數的高階函數)函數

 

再來講閉包有什麼用? 閉包減小了參數的傳遞數量, 設計閉包是爲了增長代碼重複利用。還有的文章中說到,閉包是爲了方便並行計算設計的,隨着咱們深刻學習,會繼續充實這篇文章,發覺閉包的更多做用。另外是否是跟裝飾器有點像呢?其實本質上,decorator就是一個返回函數的高階函數,閉包也是一個返回函數的高階函數。從這個角度上說 裝飾器也是閉包,閉包也是裝飾器。區別在於裝飾器但願在代碼運行期間動態增長功能,閉包但願簡化參數的調用提升代碼利用率學習

 

閉包的特性 __closure__ui

__closure__是內部函數的一個屬性,用來保存環境變量,用type()函數看一下,__closure__是一個tulple, 還以上邊的代碼爲例,咱們看一下環境變量都包含什麼,什麼樣的變量能夠記錄到環境變量中得以保存:

spa

 

從結果中咱們看到,num和num3被保存了下來,而num2沒有被保存,緣由很簡單,由於定義中,內部函數必須引用自由變量,num2沒有被引用。設計

再來看一個例子,幫助咱們理解,解釋器是如何保存環境變量到__closure__中來的,我把廖雪峯的例子作了修改:code

 1 def count():
 2     fs = []
 3     for i in range(1, 4):
 4         def f():
 5              return i*i 6  7     return f
 8 
 9 f = count()
10 x = None
11 x = f()12 pass

咱們單步跟進,發現,在每次循環中,f()只是聲明,沒有執行,因此每次循環,return i*i並無被執行。循環結束i = 3,在這時,count()函數返回,解釋器將環境變量 i 保存到__closure__中去,i = 3,打掃好現場,count()的堆棧,上下文撤銷對象

 

全部環境變量都是在函數閉包聲明結束是完成初始化。下面咱們用一個例子來講明:

第一步:   定義閉包以前,__closure__這個屬性沒有值

 

第二步:最關鍵的一步: 咱們發現,在閉包聲明結束的時候,內部函數的還將變量就已經肯定下來了,不須要等到執行內部函數才肯定環境變量。

 

 

  

 

閉包的不習慣

在c/c++中好像沒有閉包的概念,也沒有環境變量(自由變量)的概念,因此函數包含函數,或者外部函數返回內部函數,會形成異常,由於內部函數返回,堆棧消失,全部內部變量都不存在了。而python的閉包設計是容許返回局部變量的,這給咱們這些從c/c++轉過來的少年帶來了很大的不適應,總感受要出大事,這時候想一想__closure__屬性,python的閉包設計使推出內部函數後,沒有回收內部函數的部分資源,而是做爲環境變量保存下來了,慢慢習慣。

相關文章
相關標籤/搜索