W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
你想通過反省或者重寫類定義的某部分來修改它的行為,但是你又不希望使用繼承或元類的方式。
這種情況可能是類裝飾器最好的使用場(chǎng)景了。例如,下面是一個(gè)重寫了特殊方法 __getattribute__
的類裝飾器,可以打印日志:
def log_getattribute(cls):
# Get the original implementation
orig_getattribute = cls.__getattribute__
# Make a new definition
def new_getattribute(self, name):
print('getting:', name)
return orig_getattribute(self, name)
# Attach to the class and return
cls.__getattribute__ = new_getattribute
return cls
# Example use
@log_getattribute
class A:
def __init__(self,x):
self.x = x
def spam(self):
pass
下面是使用效果:
>>> a = A(42)
>>> a.x
getting: x
42
>>> a.spam()
getting: spam
>>>
類裝飾器通??梢宰鳛槠渌呒?jí)技術(shù)比如混入或元類的一種非常簡(jiǎn)潔的替代方案。比如,上面示例中的另外一種實(shí)現(xiàn)使用到繼承:
class LoggedGetattribute:
def __getattribute__(self, name):
print('getting:', name)
return super().__getattribute__(name)
# Example:
class A(LoggedGetattribute):
def __init__(self,x):
self.x = x
def spam(self):
pass
這種方案也行得通,但是為了去理解它,你就必須知道方法調(diào)用順序、super()
以及其它8.7小節(jié)介紹的繼承知識(shí)。某種程度上來講,類裝飾器方案就顯得更加直觀,并且它不會(huì)引入新的繼承體系。它的運(yùn)行速度也更快一些,因?yàn)樗⒉灰蕾?super()
函數(shù)。
如果你系想在一個(gè)類上面使用多個(gè)類裝飾器,那么就需要注意下順序問題。例如,一個(gè)裝飾器A會(huì)將其裝飾的方法完整替換成另一種實(shí)現(xiàn),而另一個(gè)裝飾器B只是簡(jiǎn)單的在其裝飾的方法中添加點(diǎn)額外邏輯。那么這時(shí)候裝飾器A就需要放在裝飾器B的前面。
你還可以回顧一下8.13小節(jié)另外一個(gè)關(guān)于類裝飾器的有用的例子。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: