Consider that code:
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"
Here I have a base class A, that has a metaclass that generate method.
Than I have Decorator class decorator, that adds some effect to the method of a decorated class.
It works perfectly on decorated class B, but its effect is not inheritable and hence D does not inherit that effect.
Thats what I want to achieve - learn how to make inheritable class decorators. Or it can be called as metaclass mixins.
How to achieve this effect? All my tries with metaclasses failed with metaclass conflict error.
Both classes
BandDhave their own reference to themethod. That's because you assign it in yourMeta's__init__method every time new class is creating. You can check it by viewing__dict__attribute (likeprint(D.__dict__)).To achieve inheritance behavior class
Dmust not contain their ownmethod, in such way it will be taken from parent classBwhich'smethodindeed decorated.From the said above I propose you the following solution:
The result of the execution of this code will be as following: