1.裝飾類
下面,直接來看代碼是如何實作裝飾類的:
defdecorator(aClass):classnewClass:def __init__(self, age):
self.total_display=0
self.wrapped=aClass(age)defdisplay(self):
self.total_display+= 1
print("total display", self.total_display)
self.wrapped.display()returnnewClass
@decorator # 接受一個類參數classBird:def __init__(self, age):
self.age=agedefdisplay(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的次數了
2.裝飾器捕捉異常
有一個check類,其中有方法read_value()。由于某些原因,方法read_value有可能抛出異常而使程式崩潰,是以需要對整個方法做try....except處理,如:
沒有捕捉異常之前:
classcheck(object):def __init__(self):pass
defreceive(self):print('receive from exception.')defread_value(self):print('here i will do something')'a' + 1 # 這裡會報異常c=check()
c.read_value()
加了try....except捕捉異常後:
classcheck(object):def __init__(self):pass
defreceive(self):print('receive from exception.')defread_value(self):try:print('here i will do something')'a' + 1
exceptException as e:print(e)
c=check()
c.read_value()
雖然程式不會報出異常,但這樣處理,有些醜陋。來看看裝飾器是如何處理的:
defcatch_exception(func):def wrapper(*args,**kwargs):try:
u= func(*args,**kwargs)returnuexceptException:return 'an exception raised'
returnwrapperclasscheck(object):def __init__(self):pass
defreceive(self):print('receive from exception.')
@catch_exceptiondefread_value(self):print('here i will do something')'a' + 1c=check()
c.read_value()
很好,使用裝飾器,來裝飾函數,這樣使我們的代碼更加pythonic。但是,如果程式報出異常後,調用類中的另外一個方法,那怎麼辦?很簡單,給裝飾器加上一個參數self:
defcatch_exception(func):def wrapper(self,*args,**kwargs):try:
u= func(self,*args,**kwargs)returnuexceptException:
self.receive()return 'an exception raised'
returnwrapperclasscheck(object):def __init__(self):pass
defreceive(self):print('receive from exception.')
@catch_exceptiondefread_value(self):print('here i will do something')'a' + 1c=check()
c.read_value()
有木有感覺,很神奇。
3.裝飾器注意事項
3.1函數的屬性會發生變化
裝飾器動态建立的新函數替換原來的函數,但是,新函數缺少很多原函數的屬性,如docstring和名字。