<p>下面是如何使用元类来实现这一点。在python3.8上测试过。应该像3.6版和更高版本一样工作。诚然,这有点复杂,使用另一种技术可能更好。在</p>
<pre><code>from abc import ABCMeta, abstractmethod
from functools import wraps
from inspect import isfunction
class InheritedDecoratorMeta(ABCMeta):
def __init__(cls, name, bases, attrs):
for name, attr in attrs.items():
for base in bases:
base_attr = base.__dict__.get(name)
if isfunction(base_attr):
inherited_decorator = getattr(base_attr, 'inherited_decorator', None)
if inherited_decorator:
setattr(cls, name, inherited_decorator()(attr))
break
def inherited_decorator(decorator, result_callback):
def inner_decorator(method):
method.inherited_decorator = lambda: inherited_decorator(decorator, result_callback)
@wraps(method)
def wrapper(*args, **kwargs):
result = method(*args, **kwargs)
return result_callback(method, result, args, kwargs)
return wrapper
return inner_decorator
def returns(type_):
if not isinstance(type_, type) and type_ is not None:
raise TypeError(f'Expected type or None; got {type_}')
def callback(method, result, args, kwargs):
result_type = type(result)
if type_ is None:
if result is not None:
raise TypeError(f'Expected method {method} to return None; got {result_type}')
elif not isinstance(result, type_):
raise TypeError(f'Expected method {method} to return {type_}; got {result_type}')
return result
return inherited_decorator(returns, callback)
class MyBaseClass(metaclass=InheritedDecoratorMeta):
@returns(int)
@abstractmethod
def aye(self, a):
raise NotImplementedError
@returns(None)
@abstractmethod
def bye(self, b):
raise NotImplementedError
class MyClass(MyBaseClass):
def aye(self, a):
return a
def bye(self, b):
return b
@returns(str)
def cye(self, c):
return c
if __name__ == '__main__':
instance = MyClass()
instance.aye(1)
try:
instance.aye('1')
except TypeError as exc:
print(exc)
instance.bye(None)
try:
instance.bye(1)
except TypeError as exc:
print(exc)
instance.cye('string')
try:
instance.cye(1)
except TypeError as exc:
print(exc)
</code></pre>