上次介绍了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的对象则会报错。