Python類裝飾器


上次介紹了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的對象則會報錯。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM