上次介紹了Python的函數裝飾器,這次我們來講一講Python的類裝飾器。
Python的類裝飾器基本語法如下:
def decorator(cls): print "6666666" return cls @decorator class Model(object): def __init__(self): print "model created" if __name__ == '__main__': model = Model()
decorator即是裝飾器函數,輸入的cls是一個類,返回也是一個類(其實返回一個可調用對象就可以,例如函數)。所以其實上文的類裝飾器就相當於:
Model = decorator(Model)
由於裝飾器是在加載該模塊時運行的,因此上文代碼中裝飾器輸出的"6666666"只會在加載該模塊時輸出一次。
這只是最基本的版本,既然返回只要是一個可調用對象就可以,我們就可以對輸入的類進行一系列魔改:
class A(object): def __init__(self): print "77777" def decorator(cls): return A @decorator class Model(object): def __init__(self): print "model created" if __name__ == '__main__': model = Model() print model
輸出為:
77777
<__main__.A object at 0x00B0F850>
可以看到,通過類裝飾器,已經把返回的類悄悄地進行了替換,最終生成的其實是A的對象。
類裝飾器可以對類對象進行修改:
def decorator(cls): cls.test_val = 1 return cls @decorator class Model(object): test_val = 0 def __init__(self): pass if __name__ == '__main__': model = Model() print model.test_val
經過類裝飾器的修飾,Model類的test_val值已經被改成了1。
類裝飾器也可以帶參數:
def decorator(num): print num def dec2(cls): return cls return dec2 @decorator(1) class Model(object):
def __init__(self): pass
最后要注意的是,對於繼承關系,若f裝飾了類A,類B繼承了A,則產生B的對象時仍然會調用裝飾器f,但裝飾器f只會修飾類A。如下代碼所示:
def decorator(num): print num def dec2(cls): print cls return cls return dec2 def decorator2(cls): print cls return cls @decorator(1) class Model(object): test_val = 0 def __init__(self): pass @decorator2 class SubModel(Model): def __init__(self): pass if __name__ == '__main__': model = SubModel()
得到的輸出為:
1 <class '__main__.Model'> <class '__main__.SubModel'>
第一行和第二行是由decorator輸出的,第三行是由decorator2輸出的。對decorator來說,它只知道Model的存在,因此在decorator中調用SubModel的對象則會報錯。