Python中的閉包和修飾器

2021-09-25 13:12:40 字數 3364 閱讀 9929

python對閉包的官方說法:閉包表示乙個內部函式裡對外部作用域(但不是全域性作用域)的變數進行引用,就認為內部函式是閉包。

閉包可以形象的理解為乙個封閉的包裹,這個包裹就是乙個函式,且這個函式有乙個特點,它將外部作用域中的變數也包裹進去了。

閉包意味著,如果呼叫乙個函式a,這個函式a返回乙個函式b,那麼稱這個返回的函式b為閉包。

def

func

(name)

:#func為外部函式a

deffunc1

(age)

:#func1為內部函式b,且內部函式將外部作用域中的變數name也包裹進去,形成閉包

print

('name:'

,name,

'age:'

,age)

#此處呼叫的name為外部作用域(func函式的作用域)中的變數

return func1 #返回乙個func1的函式物件,也就是乙個閉包,其中帶有變數name

my_age = func(

'bigboss'

)#用變數my_age來接收func返回的函式物件

my_age(19)

#相當於呼叫func1(19)

my_age = func(

'bigbigboss'

)my_age(

20)

在上述**中,當呼叫函式func(『bigboss』)時就產生乙個閉包func1(),並用my_age來接收,注意此時func函式的傳參name就是呼叫時func函式的實參。

在該示例中,閉包func1()包裹了外部變數name,這表示當函式func()的生命週期結束後,變數name依然會存在,應為它被閉包引用了,所以不會被系統**,故才可以被閉包函式func1()和函式my_age()使用。

my_age接受這個閉包後就相當於給閉包取了個叫做my_age的名字,故my_age(age) == func1(age),注意此時func1函式的傳參age就是my_age函式的實參。

運算結果

name: bigboss age: 19

name: bigbigboss age: 20

def

hello_counter

(num =0)

:#預設引數num的初始化為0

count = num #count作為相對於函式counter()的外部作用域中的引數

defcounter()

:#閉包

nonlocal count #告訴直譯器這個count變數是在外部定義的

count +=

1print

('次數:'

,count)

return counter #返回閉包

hello = hello_counter(

)#使用變數hello接收函式物件counter

hello(

)hello(

)#呼叫兩次函式hello()

在上述**中,外部函式將num賦值給count,作為計數使用。

首先使用變數hello來接受函式hello_counter()返回的閉包counter(),故此時hello() == counter(),故每呼叫一次hello()就相當於呼叫一次counter(),而閉包counter()能夠讓外部變數count自增,因此可以達到計算函式呼叫次數的目的。

注:此處用到了python關鍵字nonlocal,該關鍵字的作用是告訴直譯器這個count變數實在函式counter()的外部定義了,有了這個關鍵字,python就會從外層函式尋找變數count。

運算結果

次數: 1

次數: 2

在python語言中,可以使用裝飾器給不同的函式或類插入相同的功能,且不影響原有函式和類的功能,還能新增新的功能。

python中使用@符號來實現裝飾器,在定義裝飾器裝飾函式或類時,使用「@裝飾器名稱」的形式將符號「@」放在函式或類的定義行之前。

要想使用裝飾器來裝飾乙個函式或類,必須先定義這個裝飾器。在python中,定義裝飾器的格式與定義普通函式的格式完全一致,只不過裝飾器函式的引數必須要有函式或類物件。

然後再裝飾器函式中重新定義乙個新的函式或類,並且再其中執行某些功能前後使用被裝飾的函式或類。

最後返回這個新定義的函式或類。

def

func1

(func)

:#func為被裝飾的函式物件,符合「裝飾器函式的引數必須要有函式物件或類物件」這一條件

deffunc2

(x,y)

:#func2()為再裝飾函式中重新定義的乙個函式,並返回了被裝飾的函式func

x +=

1 y +=

2return func(x,y)

return func2 #最後返回這個新定義的函式

@func1 #使用裝飾器func1來裝飾函式sum

defsum

(a,b)

:print

('結果為:'

, a + b)

sum(1,

2)

**解讀

裝飾器@func1其實可以看作func1(sum)(a,b),它將函式sum作為函式物件傳給了func1,然後func1返回乙個新定義的函式物件func2,故可以理解為func1(sum) == func2

sum的引數a和b傳給了func2的x和y,故又可以理解為func1(sum)(a,b) == func2(a,b) == func2(x,y),之後發生新定義的函式func2的呼叫。

又新定義的函式返回的是被裝飾函式func的呼叫,而此時的func就是實參sum函式,故此處發生了sum函式的呼叫,而呼叫的引數a和b**於變化後的x和y,故裝飾器使函式sum加入了一些新的功能(這些功能包裝在新定義的函式func2中)

綜上可總結出下列關係:@func1 == func1(sum)(a,b) == func2(a,b) == func2(x,y) == func(x,y)

運算結果

結果為: 6
參考文獻

非同步圖書 // python程式設計——從入門到精通 葉維忠編著 人民郵電出版社

python中閉包和裝飾器

前言 程式語言發展的過程中,我們為了提高 利用率,發明了函式式程式設計。函式將 封裝起來,我們需要用到此功能函式的時候,呼叫一下就可以了。但是使用的過程中,也遇到了一些問題,比如函式實現的功能不夠,或者跟我們要實現的功能有些差別。腫麼辦呢?開啟函式內部 重新寫?可以嗎?可以!但是這就違背了函式式程式...

python中閉包 python中的閉包

一 定義 如果在乙個內部函式裡,對在外部作用域 但不是在全域性作用域 的變數進行引用,那麼內部函式就被認為是閉包 closure 這個定義是相對直白的,閉包有三個條件 1.函式巢狀 2,內部函式呼叫外部函式的變數 3.返回內部函式 defa a defb b s a breturnsreturnb ...

python 閉包 Python中的閉包

一 什麼是閉包 在談之前,我們先來說說作用域,變數的作用域無非就兩種 全域性變數和區域性變數。函式內部可以直接讀取全域性變數,但是在函式外部無法讀取函式內部的區域性變數。出於種種原因,我們有時候需要獲取到函式內部的區域性變數。但是,正常情況下,這是辦不到的!只有通過變通的方法才能實現。於是就引入了閉...