分类目录:《系统学习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.