考虑一下代码:
class Meta(type):
def __init__(cls, name, bases, attrs):
def method(self):
print('generated method call')
cls.method = method
super(Meta, cls).__init__(name, bases, attrs)
class A(object):
__metaclass__ = Meta
def method(self):
raise NotImplementedError
def decorator(fn):
def wrapper(*args, **kwargs):
print('decorator call')
return fn(*args, **kwargs)
return wrapper
class Decorator(object):
"""Mysterious mixin that should wrap `method` with `decorator`
at class generation time. And this effect should work on subclasses too!
"""
def __call__(self, cls):
cls.method = decorator(cls.method)
return cls
@Decorator()
class B(A):
pass
B().method() # outputs "decorated call generated method call"
class D(B):
pass
D().method() # outputs only "generated method call"
这里我有一个基类A
,它有一个生成method
的元类。
比我有Decorator
类装饰器,它会对装饰类的method
产生一些影响。
它在装饰类B
上完美运行,但其效果不可继承,因此D
不会继承该效果。
这就是我想要实现的目标 - 学习如何创建可继承的类装饰器。或者它可以被称为元类混合。
如何实现这种效果?我对元类的所有尝试均因metaclass conflict
错误而失败。
答案 0 :(得分:0)
B
和D
这两个类都有自己对method
的引用。这是因为您每次创建新课程时都会在Meta
__init__
方法中进行分配。您可以通过查看__dict__
属性(例如print(D.__dict__)
)来查看。
要实现继承行为,类D
不能包含自己的method
,这样它将从父类B
中获取method
装饰。
从上述说法中我提出以下解决方案:
def decorator(cls):
def _dec(original_method):
def _method(*args, **kwargs):
print('{cls_name} decorated: '.format(cls_name=cls.__name__), end='')
return original_method(*args, **kwargs)
return _method
cls.method = _dec(cls.method)
return cls
class A():
def method(self):
pass
@decorator
class B(A):
pass
class D(B):
pass
if __name__ == '__main__':
A().method() or print('A')
B().method() or print('B')
D().method() or print('D')
执行此代码的结果如下:
A
B decorated: B
B decorated: D