分类目录:《系统学习Python》总目录

用于函数装饰器的众多技术也同样用于新的类装饰器的编写,但是一些技术可能包含两层的扩增,以便同时管理实例构造函数调用和实例接口访问。由于类装饰器也是一个返回可调用对象的可调用对象,因此大多数函数和类的组合已经足够了。

无论怎样编写,装饰器的返回结果就是随后创建实例时所运行的。例如,要在一个类创建之后直接管理它,返回最初的类自身:

def decorator(C):
    # 对C进行处理
    return C

@decorator
class C:    # C = decorator(C)
    pass

为了插人一个包装器层来拦截随后的实例创建调用,可返回一个不同的可调用对象:

def decorator(C):
    # 返回一个带有__call__函数的class

@decorator
class C:    # C = decorator(C)
    pass

这样的一个类装饰器返回的可调用对象,通常创建并返回最初的类的一个新实例,并以某种方式扩展以管理其接口。例如,下面的装饰器插人一个对象来拦截类实例的未定义属性:

def decorator(C):
    class Wrapper:
        def __init__(self, *args):
            self.wrapper = cls(*args)
        def __getattr__(self, name):
            return getattr(self.wrapper , name)
        return Wrapper

@decorator
class C:    # C = decorator(C)
    def __init__(self, x, y):
        self.attr = 'spam'

x = C(6, 7)
print(x.attr)

在这个例子中,装饰器把类的名称重新绑定到另一个类,这个类在外层作用域中保持了最初的类,并且当调用的时候,这个类创建并嵌人了最初类的一个实例。当之后从该实例获取一个属性的时候,包装器的_getattr_拦截了它,并且将其委托给最初的类的嵌人实例。此外,每个被装饰的类都创建一个新的作用域,它记住了最初的类

就像函数装饰器一样,类装饰器通常可以编写为一个创建并返回可调用对象的“工厂”函数,或者编写为一个创建并返回类的“工厂”函数,该类使用__init____cal__l方法来拦截调用操作,还可以编写为由此产生的一系列组合。工厂函数通常在外层作用域引用中保持状态,而类通常在属性中保持状态。

参考文献:
[1] Mark Lutz. Python学习手册[M]. 机械工业出版社, 2018.