裝飾器(decorator)是一種高階python語法。裝飾器可以對乙個函式、方法或者類進行加工。在python中,我們有多種方法對函式和類進行加工,比如在python閉包中,我們見到函式物件作為某乙個函式的返回結果。相對於其它方式,裝飾器語法簡單,**可讀性高。因此,裝飾器在python專案中有廣泛的應用。
裝飾器最早在python 2.5中出現,它最初被用於加工函式和方法這樣的可呼叫物件(callable object,這樣的物件定義有__call__方法)。在python 2.6以及之後的python版本中,裝飾器被進一步用於加工類。
我們先定義兩個簡單的數學函式,乙個用來計算平方和,乙個用來計算平方差:
#get square sum
defsquare_sum(a, b):
return a**2 + b**2
#get square diff
defsquare_diff(a, b):
return a**2 - b**2
print(square_sum(3, 4))print(square_diff(3, 4))
在擁有了基本的數學功能之後,我們可能想為函式增加其它的功能,比如列印輸入。我們可以改寫函式來實現這一點:
#modify: print input
#get square sum
defsquare_sum(a, b):
print("
intput:
", a, b)
return a**2 + b**2
#get square diff
defsquare_diff(a, b):
print("
input
", a, b)
return a**2 - b**2
print(square_sum(3, 4))print(square_diff(3, 4))
我們修改了函式的定義,為函式增加了功能。
現在,我們使用裝飾器來實現上述修改:
defdecorator(f):
defnew_f(a, b):
print("
input
", a, b)
return
f(a, b)
return
new_f
#get square sum
@decorator
defsquare_sum(a, b):
return a**2 + b**2
#get square diff
@decorator
defsquare_diff(a, b):
return a**2 - b**2
print(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)。這樣,就為裝飾器的編寫和使用提供了更大的靈活性。
#def pre_str(pre=''
):
#old decorator
defdecorator(f):
defnew_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**2
print(square_sum(3, 4))
print(square_diff(3, 4))
上面的pre_str是允許引數的裝飾器。它實際上是對原有裝飾器的乙個函式封裝,並返回乙個裝飾器。我們可以將它理解為乙個含有環境參量的閉包。當我們使用@pre_str('^_^')呼叫的時候,python能夠發現這一層的封裝,並把引數傳遞到裝飾器的環境中。該呼叫相當於:
square_sum = pre_str('^_^') (square_sum)
在上面的例子中,裝飾器接收乙個函式,並返回乙個函式,從而起到加工函式的效果。在python 2.6以後,裝飾器被拓展到類。乙個裝飾器可以接收乙個類,並返回乙個類,從而起到加工類的效果。
defdecorator(aclass):
class
newclass:
def__init__
(self, age):
self.total_display =0
defdisplay(self):
self.total_display += 1
print("
total display
", self.total_display)
return
newclass
@decorator
class
bird:
def__init__
(self, age):
self.age =age
defdisplay(self):
print("
my age is
",self.age)
eaglelord = bird(5)
for i in range(3):
eaglelord.display()
通過修改,我們的bird類可以顯示呼叫display的次數了。
裝飾器的核心作用是name binding。這種語法是python多程式設計正規化的又乙個體現。大部分python使用者都不怎麼需要定義裝飾器,但有可能會使用裝飾器。鑑於裝飾器在python專案中的廣泛使用,了解這一語法是非常有益的。
」
python裝飾器以及裝飾器的深入
1.通 裝飾器回顧 通過裝飾器的模板格式 def fn def inner args,kwargs 增加的內容 ret fn args,kwargs 增加的內容 return ret return inner2.函式的有 資訊 1 獲取函式的注釋資訊,示例 def fun a,b,c 函式的功能 p...
深入理解Python裝飾器
主要內容 l local 函式內部作用域 e enclosing 函式內部與內嵌函式之間 g global 全域性作用域 b build in 內建作用域 closure 內部函式中對enclosing作用域的變數進行引用 函式的實質與屬性 函式是乙個物件 函式執行完成後內部變數 函式屬性 函式返回...
深入學習python裝飾器
裝飾器 用於修改其他函式功能的物件,python裡一切都是物件,顧裝飾器可以是函式也可以是類 單個函式接收裝飾器,通過類可以實現多個功能,再通過繼承可以實現增強功能 一般用於許可權驗證和日誌記錄模組。函式裝飾器 import time from functools import wraps 計算函式...