Python自由之路(五)Pyhton 閉包

2022-04-03 14:56:36 字數 1602 閱讀 4682

如果在乙個內部函式裡,對在外部作用域(但不是在全域性作用域)的變數進行引用,那麼內部函式就被認為是閉包(closure).閉包在函式式程式設計中是乙個重要的概念。語法上看比較簡單,但是用處卻是相當廣泛的。

在python 2.1版本以前,只有全域性域和區域性作用域,而在2.1以後的版本中我們可以使用靜態巢狀域,如像下面這樣的巢狀函式中,在以前,內部函式是不能訪問外部函式作用域中的變數的。

def foo():

m = 3

def bar():

n = 4

print m + n

print m

bar()

而在現在的版本中可以完美執行,而bar()中的 m 就是乙個既不屬於全域性域又不屬於區域性域的閉包變數,它存活在乙個函式的命名空間和作用域---巢狀作用域。而在閉包中對巢狀作用域中的訪問規則與上面討論的global是一樣的。即在對閉包變數 m 的重新宣告之前引用 m 都會引發異常

def foo():

m = 3

def bar():

print m  #unboundlocalerror

m=4print m

bar()

unboundlocalerror: local variable 'm' referenced before assignment

為什麼會這樣呢?其實是因為m的型別有關,我們知道pyhton中的基本資料型別分為可變和不可變,對於不可變型別的賦值,其實是重新定義乙個新的變數物件,並深拷貝原物件到新物件,參考str型別說明。 如果將上面的 m 宣告成可變型別list,那就不會產生這個異常了。

def foo():

m = [3]

def bar():

print m[0]

m[0]=4

print m[0]

bar()

關於可變型別與不可變型別的說明,這裡就不展開說了,大家可以看api document

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

def hellocounter (name):

count=[0]

def counter():

count[0]+=1

print 'hello,',name,',',str(count[0])+' access!'

return counter

hello = hellocounter('ysisl')

hello()

hello()

hello()

console output:

hello, ysisl , 1 access!

hello, ysisl , 2 access!

hello, ysisl , 3 access!

這個例子中,hellocounter(name)返回了乙個內部函式counter的引用,就像c++中指向函式的指標一樣,我們把這個引用用乙個變數hello來儲存,那麼這個變數就代表了這個counter函式,為什麼對hello()的反覆呼叫能保持閉包變數count的自增,而不是釋放後再重新分配?因為count不是counter的區域性變數,它是乙個在hellocounter()範圍內游離於counter之外的變數,只有當hellocounter(name)被呼叫時,count才被重新分配新的記憶體位址。

Python 自由之路(一)ImageCrawl

每個程式設計師都應該有自己最精通的一門語言,也許是緣分吧 很早就認識了python,一直沒多大在意,可是現在越來越發現python在成長,隨著python 3k的發布,可以說,它的語法功能幾乎囊括了現代程式語言中所有的精華。最關鍵的是,它是開源的,開源意味著自由,集體共享的智慧型。自由之路開始了,呵...

leetcode 自由之路

leetcode每日一題 這應該就是個廣度優先搜尋的實現,具體操作方法就是每次找到下一步的能到達的所有點,因為有重合,可以篩選一部分 我可能寫的比較亂,也可能有其他解決方法,但是我有點懶了 public intfindrotatesteps string ring,string key 開始遍歷ke...

《財務自由之路》

古老的格言自有其道理 所有的傻瓜都生活在希望和等待之 中。你的財務狀況對於建立自信極為重要。你的財務狀況應該成為乙個你不懼怕任何阻礙的證明。你不能讓自己的財務狀況破壞你的自信程度。沒有自信的生活只能 叫作生存。你永遠都不會知道自己的潛能。你從不冒險,從不成長,從 不應對處境做出反抗,從不充分開發自己...