引子
大概一個(gè)月前银室,一個(gè)同事問(wèn)涂佃,什么是"閉包",然后整個(gè)月好像都在糾結(jié)這個(gè)問(wèn)題啊喂蜈敢。辜荠。。其實(shí)搜搜概念抓狭,網(wǎng)上有一大堆伯病,研究一下其實(shí)也不復(fù)雜。然后不知道什么鬼總感覺(jué)這東西跟裝飾器有什么數(shù)不清楚的關(guān)系胺窆(后面寫(xiě)一篇)午笛,于是膨蛮,又折騰了一下,然后季研,尼瑪?shù)牧硪粋€(gè)同事問(wèn)敞葛,"為什么我們需要閉包"
然后我就無(wú)言以對(duì)啊,搞明白一個(gè)概念与涡,如果沒(méi)有什么實(shí)踐價(jià)值惹谐,有個(gè)卵用啊于是在接下來(lái)的時(shí)間不停的想啊想啊想。驼卖。氨肌。終于今晚想到了一個(gè)絕佳的例子,怎么樣也要記錄一下吧
例子
廢話不多suo了酌畜。直接上例子吧怎囚。比如math包里面有個(gè)log函數(shù),可是我并不知道log2(8)這玩意要寫(xiě)成math.log(2, 8)
還是math.log(8, 2)
桥胞,而且我也不想log2寫(xiě)一個(gè)log10再寫(xiě)一個(gè)吧恳守。。贩虾。所以催烘,為了少碼幾個(gè)字,我們可以這樣寫(xiě):
import math
def my_log(a):
def wrapper(N):
return math.log(N, a)
return wrapper
if __name__ == "__main__":
log2 = my_log(2)
lg = my_log(10)
print log2(8)
print lg(100)
是的缎罢,通過(guò)log2或者lg伊群,就可以直接計(jì)算以2為底或者以10為底的數(shù)的對(duì)數(shù)了。而且log2(8)
這種寫(xiě)法策精,也比較符合正常人的想法舰始。順帶,我們也不需要再單獨(dú)定義兩個(gè)函數(shù)了咽袜,O(∩_∩)O~
其實(shí)丸卷,估計(jì)不用閉包也會(huì)有辦法實(shí)現(xiàn)同樣的功能,但是閉包絕對(duì)提供了一種更為優(yōu)(tou)雅(lan)的實(shí)現(xiàn)方式酬蹋。下面我們說(shuō)說(shuō)什么是閉包及老。
定義
反正抽莱,我是不會(huì)告訴你范抓,它的官方定義是:
如果在一個(gè)內(nèi)部函數(shù)里,對(duì)在外部作用域(但不是在全局作用域)的變量進(jìn)行引用食铐,那么內(nèi)部函數(shù)就被認(rèn)為是閉包(closure)
如果要用一個(gè)例子來(lái)解釋上面這段話的話匕垫,可以參考以下代碼:
def outer(outer_para):
def inner(inner_para):
return outer_para + inner_para
return inner
if __name__ == "__main__":
func = outer(5)
print func(10)
接下來(lái)再補(bǔ)充完善一下:
- 必須有一個(gè)內(nèi)嵌函數(shù)(nested function),也就是在函數(shù)內(nèi)部定義一個(gè)函數(shù)虐呻,比如例子中的inner
- 必須在內(nèi)嵌函數(shù)中調(diào)用上層函數(shù)中的變量象泵,比如在inner中調(diào)用outer_para
- 上層函數(shù)必須返回內(nèi)嵌函數(shù)寞秃,也就是outer的最后一行必須是
return inner