如果在乙個內部函式裡,對在外部作用域(但不是在全域性作用域)的變數進行引用,那麼內部函式就被認為是閉包(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...
《財務自由之路》
古老的格言自有其道理 所有的傻瓜都生活在希望和等待之 中。你的財務狀況對於建立自信極為重要。你的財務狀況應該成為乙個你不懼怕任何阻礙的證明。你不能讓自己的財務狀況破壞你的自信程度。沒有自信的生活只能 叫作生存。你永遠都不會知道自己的潛能。你從不冒險,從不成長,從 不應對處境做出反抗,從不充分開發自己...