新聞中心
閉包并不是什么新奇的概念,它早在高級(jí)語(yǔ)言開(kāi)始發(fā)展的年代就產(chǎn)生了。在此之前也曾陸續(xù)報(bào)導(dǎo)了《學(xué)習(xí)Scala的閉包》、《PHP 5.3閉包語(yǔ)法初探》以及《揭開(kāi)Javascript閉包的真實(shí)面目》。閉包(Closure)是詞法閉包(Lexical Closure)的簡(jiǎn)稱(chēng)。對(duì)閉包的具體定義有很多種說(shuō)法,這些說(shuō)法大體可以分為兩類(lèi):

◆一種說(shuō)法認(rèn)為閉包是符合一定條件的函數(shù),比如參考資源中這樣定義閉包:閉包是在其詞法上下文中引用了自由變量的函數(shù)。
◆另一種說(shuō)法認(rèn)為閉包是由函數(shù)和與其相關(guān)的引用環(huán)境組合而成的實(shí)體。比如參考資源中就有這樣的的定義:在實(shí)現(xiàn)深約束時(shí),需要?jiǎng)?chuàng)建一個(gè)能顯式表示引用環(huán)境的東西,并將它與相關(guān)的子程序捆綁在一起,這樣捆綁起來(lái)的整體被稱(chēng)為閉包。
這兩種定義在某種意義上是對(duì)立的,一個(gè)認(rèn)為閉包是函數(shù),另一個(gè)認(rèn)為閉包是函數(shù)和引用環(huán)境組成的整體。雖然有些咬文嚼字,但可以肯定第二種說(shuō)法更確切。閉包只是在形式和表現(xiàn)上像函數(shù),但實(shí)際上不是函數(shù)。函數(shù)是一些可執(zhí)行的代碼,這些代碼在函數(shù)被定義后就確定了,不會(huì)在執(zhí)行時(shí)發(fā)生變化,所以一個(gè)函數(shù)只有一個(gè)實(shí)例。
閉包在運(yùn)行時(shí)可以有多個(gè)實(shí)例,不同的引用環(huán)境和相同的函數(shù)組合可以產(chǎn)生不同的實(shí)例。所謂引用環(huán)境是指在程序執(zhí)行中的某個(gè)點(diǎn)所有處于活躍狀態(tài)的約束所組成的集合。其中的約束是指一個(gè)變量的名字和其所代表的對(duì)象之間的聯(lián)系。那么為什么要把引用環(huán)境與函數(shù)組合起來(lái)呢?這主要是因?yàn)樵谥С智短鬃饔糜虻恼Z(yǔ)言中,有時(shí)不能簡(jiǎn)單直接地確定函數(shù)的引用環(huán)境。
閉包和函數(shù)對(duì)象本質(zhì)上是同一種東西,閉包是函數(shù)對(duì)象的簡(jiǎn)化。閉包將環(huán)境數(shù)據(jù)保存在func_closure中,函數(shù)對(duì)象則將相關(guān)數(shù)據(jù)保存在對(duì)象中。二者均可用于filter、map、reduce等函數(shù)中。
下面分別使用閉包和函數(shù)對(duì)象來(lái)做同一件事情,感覺(jué)二者非常相似。
- ?[Copy to clipboard]View Code PYTHONIn [68]: class counter_class():
- def __init__(self, start_at):
- self.start_at = start_at
- def __call__(self):
- self.start_at += 1
- return self.start_at
- ....:
- ....:
- In [74]:
- In [75]: c1 = counter_class(5)
- In [76]: c1()
- Out[76]: 6
- In [77]: c1()
- Out[77]: 7
- In [78]: c1()
- Out[78]: 8
- In [80]: def counter_closure(start_at = 0):
- count = [start_at]
- def incr():
- count[0] += 1
- return count[0]
- return incr
- ....:
- In [86]: c2 = counter_closure(5)
- In [87]: c2()
- Out[87]: 6
- In [88]: c2()
- Out[88]: 7
- In [89]: c2()
- Out[89]: 8
支持閉包的語(yǔ)言有這樣的特性:
1、函數(shù)是一階值(First-class value),即函數(shù)可以作為另一個(gè)函數(shù)的返回值或參數(shù),還可以作為一個(gè)變量的值。
2、函數(shù)可以嵌套定義,即在一個(gè)函數(shù)內(nèi)部可以定義另一個(gè)函數(shù)。
顯然Python對(duì)這兩個(gè)特性支持都非常好,Java要想支持閉包改動(dòng)就有點(diǎn)大了。在Python中函數(shù)同類(lèi)差不多,而在Java中類(lèi)是最小的組織單元,目前JDK 6.0上面兩個(gè)特性一個(gè)都不支持。至于C++這樣更底層的語(yǔ)言要支持閉包估計(jì)是不可能的。
Python中的閉包
Python因其簡(jiǎn)單易學(xué)、功能強(qiáng)大而擁有很多擁護(hù)者,很多企業(yè)和組織在使用這種語(yǔ)言。Python使用縮進(jìn)來(lái)區(qū)分作用域的做法也十分有特點(diǎn)。下面是一個(gè)Python的例子:
- 清單 6. Python 1
- def addx(x):
- def adder (y): return x + y
- return adder
- add8 = addx(8)
- add9 = addx(9)
- print add8(100)
- print add9(100)
在Python中使用def來(lái)定義函數(shù)時(shí),是必須有名字的,要想使用匿名函數(shù),則需要使用lambda語(yǔ)句,象下面的代碼這樣:
- 清單 7. Python 2
- def addx(x):
- return lambda y: x + y
- add8 = addx(8)
- add9 = addx(9)
- print add8(100)
- print add9(100)
【編輯推薦】
- 揭開(kāi)Javascript閉包的真實(shí)面目
- 談PHP閉包特性在實(shí)際應(yīng)用中的問(wèn)題
- PHP 5.3閉包語(yǔ)法的具體講解
- 淺析Javascript閉包的特性
- Javascript利用閉包循環(huán)綁定事件
當(dāng)前標(biāo)題:Python閉包的概念、形式與應(yīng)用
文章位置:http://m.5511xx.com/article/cdgscdg.html


咨詢(xún)
建站咨詢(xún)
