Python中的閉包使用及作用_第1頁
Python中的閉包使用及作用_第2頁
Python中的閉包使用及作用_第3頁
Python中的閉包使用及作用_第4頁
Python中的閉包使用及作用_第5頁
已閱讀5頁,還剩1頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第Python中的閉包使用及作用目錄1.什么是閉包2.閉包的實例3.閉包和裝飾器的區(qū)別

1.什么是閉包

當我們在外部函數(shù)中定義了一個內(nèi)部函數(shù),并且內(nèi)部函數(shù)能夠讀取到外部函數(shù)內(nèi)的變量,這種函數(shù)我們就稱為閉包。簡單來說,閉包就是能夠讀取外部函數(shù)內(nèi)的變量的函數(shù)。

閉包的架子大概是這樣:

defdemo_outer(x):

defdemo_inner(y):

print("x的值:{},y的值:{},x+y的值:{}".format(x,y,x+y))

returndemo_inner

do=demo_outer(12)

do(34)

上面代碼執(zhí)行結(jié)果如下:

x的值:12,y的值:34,x+y的值:46

上面的閉包代碼,和我們之前學習的裝飾器類似,我們在外部函數(shù)demo_outer下定義了一個內(nèi)部函數(shù)demo_inner,并且外部函數(shù)的返回值就是內(nèi)部函數(shù),同時在內(nèi)部函數(shù)中,我們引用到了外部函數(shù)的變量x,而閉包的作用就是可以將外層函數(shù)的變量保存在內(nèi)存中而不被銷毀。

2.閉包的實例

我們先準備一個函數(shù)add(),每次調(diào)用該函數(shù)都只能傳一個數(shù)num,每次返回的結(jié)果都是基于上一次結(jié)果的值sum進行累加操作。例如,sum的默認值為0,如果我們依次調(diào)用add(10)、add(20)、add(30)后,期望得到的最終結(jié)果是sum=60。

對于該問題,因為需要在函數(shù)內(nèi)部對函數(shù)外部的變量進行處理,我們可能會考慮使用global來處理。

sum=0

defget_add_sum(num):

globalsum

sum+=num

returnsum

print(get_add_sum(10))#輸出:10

print(get_add_sum(20))#輸出:30

print(get_add_sum(30))#輸出:60

print(sum)#輸出:60

上面代碼中,我們在函數(shù)中通過全局變量global將sum聲明為全局變量,最終返回的結(jié)果也符合我們的期望。但因為全局變量太靈活了,不同模塊函數(shù)都能自由訪問到全局變量,所以一般不推薦在函數(shù)內(nèi)部中定義全局變量。

對于上面的問題,除了使用全局變量外,我們還可以通過閉包來實現(xiàn)。

sum=0

defget_add_sum(sum):

defadd_num(num):

nonlocalsum

sum+=num

returnsum

returnadd_num

add=get_add_sum(sum)

print(add(10))#輸出:10

print(add(20))#輸出:30

print(add(30))#輸出:60

print(sum)#輸出:0

在上面的閉包函數(shù)中,定義了外層函數(shù)和內(nèi)層嵌套函數(shù),執(zhí)行過程中,調(diào)用外層函數(shù)get_add_sum返回的就是內(nèi)層嵌套函數(shù)add_num,因為Python中函數(shù)也是對象,所以可以直接返回add_num。

而在內(nèi)層嵌套函數(shù)中則實現(xiàn)了我們想要的累加操作,在這里我們需使用關(guān)鍵字nonlocal來聲明外層函數(shù)中的變量,否則無法對外層函數(shù)中的變量進行修改,其作用域只在閉包函數(shù)里面,所以當我們在最后打印sum最終結(jié)果,輸出的仍然是其初始值0。

我們再來看一個例子:

defouter():

res=[]

foriinrange(3):

print("外部的i值:{}".format(i))

definner(x):

print("內(nèi)部的i值:{}".format(i))

returni+x

res.append(inner)

returnres

temp=outer()

res=[i(10)foriintemp]

print(res)

上面代碼的執(zhí)行結(jié)果如下:

外部的i值:0

外部的i值:1

外部的i值:2

內(nèi)部的i值:2

內(nèi)部的i值:2

內(nèi)部的i值:2

[12,12,12]

可以看到res的結(jié)果并不是[10,11,12],因為i是外層函數(shù)的變量,并且其值是按0,1,2變化,因為該函數(shù)中無法保存外層函數(shù)的變量,故對于內(nèi)部函數(shù),其實際只能訪問到最后外部變量的值2,導致最終結(jié)果為:[12,12,12]。

在這里,我們可以使用閉包來保存函數(shù)的外部變量,修改代碼如下:

defouter(i):

print("外部的i值:{}".format(i))

definner(x):

print("內(nèi)部的i值:{}".format(i))

returni+x

returninner

defdemo():

res=[]

foriinrange(3):

res.append(outer(i))

returnres

temp=demo()

res=[i(10)foriintemp]

print(res)

上面代碼的執(zhí)行結(jié)果如下:

外部的i值:0

外部的i值:1

外部的i值:2

內(nèi)部的i值:0

內(nèi)部的i值:1

內(nèi)部的i值:2

[10,11,12]

3.閉包和裝飾器的區(qū)別

在Python中,閉包傳遞的參數(shù)是變量,裝飾器傳遞的參數(shù)是函數(shù)對象,它們只是在傳參內(nèi)容上有不同。那么裝飾器是不是屬于閉包的一種呢,我們要怎么判斷一個函數(shù)是否是閉包呢?

我們可以打印閉包和裝飾器的屬性__closure__,如果一個函數(shù)是閉包,那么查看該屬性將會返回一個cell對象組成的tuple對象。

defdemo_outer(x):

defdemo_inner(y):

print("x的值:{},y的值:{},x+y的值:{}".format(x,y,x+y))

returndemo_inner

defdemo_decorator(func):

defwrapper(*args,**kwargs):

returnfunc(*args,**kwargs)

returnwrapper

@demo_decorator

defmethod():

pass

do=demo_outer(5)#閉包

print("閉包的屬性:{}".format(do.__closure__))

dd=demo_decorator(method)#裝飾器

print("裝飾器的屬性:{}".format(dd.__closure__))

執(zhí)行結(jié)果如下:

閉包的屬性:(cellat0x0000023F48C3C8E8:intobjectat0

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論