Python 基礎(chǔ)教程之閉包的使用方法
前言:
閉包(closure)是函數(shù)式編程的重要的語(yǔ)法結(jié)構(gòu)。函數(shù)式編程是一種編程范式 (而面向過(guò)程編程和面向?qū)ο缶幊桃捕际蔷幊谭妒?。在面向過(guò)程編程中,我們見(jiàn)到過(guò)函數(shù)(function);在面向?qū)ο缶幊讨校覀円?jiàn)過(guò)對(duì)象(object)。函數(shù)和對(duì)象的根本目的是以某種邏輯方式組織代碼,并提高代碼的可重復(fù)使用性(reusability)。閉包也是一種組織代碼的結(jié)構(gòu),它同樣提高了代碼的可重復(fù)使用性。
不同的語(yǔ)言實(shí)現(xiàn)閉包的方式不同。Python以函數(shù)對(duì)象為基礎(chǔ),為閉包這一語(yǔ)法結(jié)構(gòu)提供支持的 (我們?cè)谔厥夥椒ㄅc多范式中,已經(jīng)多次看到Python使用對(duì)象來(lái)實(shí)現(xiàn)一些特殊的語(yǔ)法)。Python一切皆對(duì)象,函數(shù)這一語(yǔ)法結(jié)構(gòu)也是一個(gè)對(duì)象。在函數(shù)對(duì)象中,我們像使用一個(gè)普通對(duì)象一樣使用函數(shù)對(duì)象,比如更改函數(shù)對(duì)象的名字,或者將函數(shù)對(duì)象作為參數(shù)進(jìn)行傳遞。
函數(shù)對(duì)象的作用域
和其他對(duì)象一樣,函數(shù)對(duì)象也有其存活的范圍,也就是函數(shù)對(duì)象的作用域。函數(shù)對(duì)象是使用def語(yǔ)句定義的,函數(shù)對(duì)象的作用域與def所在的層級(jí)相同。比如下面代碼,我們?cè)趌ine_conf函數(shù)的隸屬范圍內(nèi)定義的函數(shù)line,就只能在line_conf的隸屬范圍內(nèi)調(diào)用。
def line_conf(): def line(x): return 2*x+1 print(line(5)) # within the scopeline_conf()print(line(5)) # out of the scope
line函數(shù)定義了一條直線(y = 2x + 1)。可以看到,在line_conf()中可以調(diào)用line函數(shù),而在作用域之外調(diào)用line將會(huì)有下面的錯(cuò)誤:
NameError: name 'line' is not defined
說(shuō)明這時(shí)已經(jīng)在作用域之外。
同樣,如果使用lambda定義函數(shù),那么函數(shù)對(duì)象的作用域與lambda所在的層級(jí)相同。
閉包
函數(shù)是一個(gè)對(duì)象,所以可以作為某個(gè)函數(shù)的返回結(jié)果。
def line_conf(): def line(x): return 2*x+1 return line # return a function objectmy_line = line_conf()print(my_line(5))
上面的代碼可以成功運(yùn)行。line_conf的返回結(jié)果被賦給line對(duì)象。上面的代碼將打印11。
如果line()的定義中引用了外部的變量,會(huì)發(fā)生什么呢?
def line_conf(): b = 15 def line(x): return 2*x+b return line # return a function objectb = 5my_line = line_conf()print(my_line(5))
我們可以看到,line定義的隸屬程序塊中引用了高層級(jí)的變量b,但b信息存在于line的定義之外 (b的定義并不在line的隸屬程序塊中)。我們稱(chēng)b為line的環(huán)境變量。事實(shí)上,line作為line_conf的返回值時(shí),line中已經(jīng)包括b的取值(盡管b并不隸屬于line)。
上面的代碼將打印25,也就是說(shuō),line所參照的b值是函數(shù)對(duì)象定義時(shí)可供參考的b值,而不是使用時(shí)的b值。
新聞熱點(diǎn)
疑難解答
圖片精選