您可以使用在method1
创建类时包装的元类:
from functools import wraps
class MetaA(type):
def __new__(meta, name, bases, attr):
method1 = attr['method1']
if not getattr(method, '__isabstractmethod__'):
@wraps(method1)
def wrapper(self, *args, **kw):
res = method1(self, *args, **kw)
self.method2()
return res
attr['method1'] = wrapper
return super(MetaA, meta).__new__(meta, name, bases, attr)
class A(object):
__metaclass__ = MetaA
@abc.abstractmethod
def method1(self):
raise Exception("Unimplemented method")
def method2(self):
print "method1 finished"
每当创建(子)类时,这将基本上是装饰器应用于特定方法。
另一种有点骇人听闻的方法是拦截方法访问,但会起作用。您将实现一个添加包装器的__getattribute__
钩子A
:
from functools import wraps
class A(object):
@abc.abstractmethod
def method1(self):
raise Exception("Unimplemented method")
def method2(self):
print "method1 finished"
def __getattribute__(self, name):
obj = super(A, self).__getattribute__(name)
if name == 'method1':
@wraps(obj)
def wrapper(*args, **kw):
res = obj()
self.method2()
return res
return wrapper
return obj
任何一种方法都会导致:
>>> B().method1()
executing method1 from class B
method1 finished
通过使用@functools.wraps()
装饰器,包装器维护了被包装方法的几个重要属性,例如它的名称和文档字符串。