参见英文答案 > Attaching a decorator to all functions within a class 5个
让我说我的类有很多方法,我想在每一个方法上应用我的装饰,后来当我添加新方法时,我想要应用相同的装饰器,但我不想在方法声明之上写@mydecorator所有时间?
如果我调查__call__是正确的方法吗?
重要提示:以下示例似乎解决了与原始问题不同的问题.
编辑:我想以这种方式展示,这是我的问题的类似解决方案,对于任何人后来发现这个问题,使用评论中提到的mixin.
class WrapinMixin(object):
def __call__(self, hey, you, *args):
print 'entering', hey, you, repr(args)
try:
ret = getattr(self, hey)(you, *args)
return ret
except:
ret = str(e)
raise
finally:
print 'leaving', hey, repr(ret)
然后你可以在另一个
class Wrapmymethodsaround(WrapinMixin):
def __call__:
return super(Wrapmymethodsaround, self).__call__(hey, you, *args)
解决方法:
使用遍历类属性并装饰callables的函数来装饰类.如果你的类变量可能碰巧是可调用的,那么这可能是错误的做法,并且还会修饰嵌套类(Sven Marnach指出这一点),但通常这是一个相当简洁的解决方案.示例实现(请注意,这不会排除可能需要或可能不需要的特殊方法(__init__等)):
def for_all_methods(decorator):
def decorate(cls):
for attr in cls.__dict__: # there's propably a better way to do this
if callable(getattr(cls, attr)):
setattr(cls, attr, decorator(getattr(cls, attr)))
return cls
return decorate
使用这样:
@for_all_methods(mydecorator)
class C(object):
def m1(self): pass
def m2(self, x): pass
...
在Python 3.0和3.1中,callable不存在.它永远存在于Python 2.x中,并且作为isinstance(x,collections.Callable)的包装器返回到Python 3.2中,因此您可以在这些版本中使用它(或使用此定义您自己的可调用替换).