Python深入05 裝飾器
裝飾器(decorator)是一種高階Python語法。裝飾器可以 對一個函式、方法或者類進行加工。在Python中,我們有多種方法對函式和類進行加工,比如在 Python閉包中,我們見到函式物件作為某一個函式的返回結果。相對於其它方式,裝飾器語法簡單,程式碼可讀性高。因此,裝飾器在Python專案中有廣泛的應用。
裝飾器最早在Python 2.5中出現,它最初被用於加工函式和方法這樣的 可呼叫物件(callable object,這樣的物件定義有__call__方法)。在Python 2.6以及之後的Python版本中,裝飾器被進一步用於加工類。
裝飾函式和方法
我們先定義兩個簡單的數學函式,一個用來計算平方和,一個用來計算平方差:
# get square sum def square_sum(a, b): return a**2 + b**2 # get square diff def square_diff(a, b): return a**2 - b**2
print(square_sum(3, 4))print(square_diff(3, 4))
在擁有了基本的數學功能之後,我們可能想為函式增加其它的功能,比如列印輸入。我們可以改寫函式來實現這一點:
# modify: print input # get square sum def square_sum(a, b): print( " intput: " , a, b) return a**2 + b**2 # get square diff def square_diff(a, b): print( " input " , a, b) return a**2 - b**2
print(square_sum(3, 4))print(square_diff(3, 4))
我們修改了函式的定義,為函式增加了功能。
現在,我們使用裝飾器來實現上述修改:
def decorator(F): def new_F(a, b): print("input", a, b) return F(a, b) return new_F# get square sum@decoratordef square_sum(a, b): return a**2 + b**2# get square diff@decoratordef square_diff(a, b): return a**2 - b**2print(square_sum(3, 4))print(square_diff(3, 4))
裝飾器可以用def的形式定義,如上面程式碼中的decorator。裝飾器接收一個可呼叫物件作為輸入引數,並返回一個新的可呼叫物件。裝飾器新建了一個可呼叫物件,也就是上面的new_F。new_F中,我們 增加了列印的功能,並透過呼叫F(a, b)來 實現原有函式的功能。
定義好裝飾器後,我們就可以透過@語法使用了。在函式square_sum和square_diff定義之前呼叫@decorator,我們實際上將square_sum或square_diff傳遞給decorator,並將decorator返回的新的可呼叫物件賦給原來的函式名(square_sum或square_diff)。 所以,當我們呼叫square_sum(3, 4)的時候,就相當於:
square_sum = decorator(square_sum) square_sum(3, 4)
我們知道,Python中的變數名和物件是分離的。變數名可以指向任意一個物件。從本質上,裝飾器起到的就是這樣一個重新指向變數名的作用(name binding),讓同一個變數名指向一個新返回的可呼叫物件,從而達到修改可呼叫物件的目的。
與加工函式類似,我們可以使用裝飾器加工類的方法。
如果我們有其他的類似函式,我們可以繼續呼叫decorator來修飾函式,而不用重複修改函式或者增加新的封裝。這樣,我們就提高了程式的可重複利用性,並增加了程式的可讀性。
含參的裝飾器
在上面的裝飾器呼叫中,比如@decorator,該裝飾器預設它後面的函式是唯一的引數。裝飾器的語法允許我們呼叫decorator時,提供其它引數,比如@decorator(a)。這樣,就為裝飾器的編寫和使用提供了更大的靈活性。
# a new wrapper layerdef pre_str(pre=''): # old decorator def decorator(F): def new_F(a, b): print(pre + "input", a, b) return F(a, b) return new_F return decorator# get square sum@pre_str('^_^')def square_sum(a, b): return a**2 + b**2# get square diff@pre_str('T_T')def square_diff(a, b): return a**2 - b**2print(square_sum(3, 4))print(square_diff(3, 4))
上面的pre_str是允許引數的裝飾器。它實際上是對原有裝飾器的一個函式封裝,並返回一個裝飾器。我們可以將它理解為一個含有環境參量的 閉包。當我們使用@pre_str('^_^')呼叫的時候,Python能夠發現這一層的封裝,並把引數傳遞到裝飾器的環境中。該呼叫相當於:
square_sum = pre_str('^_^') (square_sum)
裝飾類
在上面的例子中,裝飾器接收一個函式,並返回一個函式,從而起到加工函式的效果。在Python 2.6以後,裝飾器被擴充到類。一個裝飾器可以接收一個類,並返回一個類,從而起到加工類的效果。
def decorator(aClass): class newClass: def __init__(self, age): self.total_display = 0 self.wrapped = aClass(age) def display(self): self.total_display += 1 print("total display", self.total_display) self.wrapped.display() return newClass @decoratorclass Bird: def __init__(self, age): self.age = age def display(self): print("My age is",self.age) eagleLord = Bird(5)for i in range(3): eagleLord.display()
在decorator中,我們返回了一個新類newClass。在新類中,我們記錄了原來類生成的物件(self.wrapped),並附加了新的屬性total_display,用於記錄呼叫display的次數。我們也同時更改了display方法。
透過修改,我們的Bird類可以顯示呼叫display的次數了。
總結
裝飾器的核心作用是name binding。這種語法是Python多程式設計正規化的又一個體現。大部分Python使用者都不怎麼需要定義裝飾器,但有可能會使用裝飾器。鑑於裝飾器在Python專案中的廣泛使用,瞭解這一語法是非常有益的。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31543790/viewspace-2666137/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Python深入分享之裝飾器Python
- 深入理解Python中的裝飾器Python
- python裝飾器2:類裝飾器Python
- Python 裝飾器Python
- Python裝飾器Python
- 1.5.3 Python裝飾器Python
- Python 裝飾器(一)Python
- python的裝飾器Python
- Python 裝飾器原理Python
- Python裝飾器模式Python模式
- python 之裝飾器(decorator)Python
- Python中的裝飾器Python
- Python裝飾器詳解Python
- python裝飾器入門探究Python
- python 裝飾器 part2Python
- day11(python)裝飾器Python
- python中裝飾器的原理Python
- Python裝飾器高階用法Python
- python 裝飾器小白學習Python
- 【python】閉包與裝飾器Python
- Python裝飾器的前世今生Python
- python的裝飾器@的用法Python
- Python 語法之裝飾器Python
- Python3 裝飾器解析Python
- Python閉包與裝飾器Python
- Python之函式裝飾器Python函式
- Python 裝飾器簡單示例Python
- python裝飾器有哪些作用Python
- python裝飾器是什麼Python
- 粗淺聊聊Python裝飾器Python
- Python迭代器&生成器&裝飾器Python
- python函數語言程式設計3(裝飾器的深入理解)Python函數程式設計
- python幾種裝飾器的用法Python
- Python學習筆記 - 裝飾器Python筆記
- Python 裝飾器你也會用Python
- Python:從閉包到裝飾器Python
- python中的裝飾器介紹Python
- python3 裝飾器全解Python