如何在不为每个方法反复输入的情况下装饰类的所有函数?

参见英文答案 > 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中,因此您可以在这些版本中使用它(或使用此定义您自己的可调用替换).

上一篇:python – 如何装饰一个类?


下一篇:23.Python函数式编程 装饰器 详解