我怎样才能装饰一个类的所有function,而无需反复input每个方法添加? Python
比方说我的类有很多方法,我想在我们的每一个应用我的装饰器,后来当我添加新的方法,我想要应用相同的装饰器,但我不想在方法声明上面写@mydecorator所有时间?
如果我看看__call__
是否正确的路?
谢谢
重要提示:下面的例子似乎解决了一个不同的问题,而不是被问到的原始问题。
编辑:编号喜欢显示这种方式,这是一个类似的解决scheme,我的问题任何人稍后发现这个问题,使用评论中提到的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)
使用遍历类的属性并装饰可调参数的函数来装饰类。 如果你有可能被调用的类variables,也可能是错误的,并且也会修饰嵌套类(Sven Marnach指出这一点),但通常这是一个相当干净和简单的解决scheme。 示例实现(请注意,这不会排除特殊方法( __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,因此您可以在这些版本中使用它(或者使用它定义自己的callable
replace)。
虽然我不喜欢使用神奇的方法,当明确的方法可以做,你可以使用这个元类。
def myDecorator(fn): fn.foo = 'bar' return fn class myMetaClass(type): def __new__(cls, name, bases, local): for attr in local: value = local[attr] if callable(value): local[attr] = myDecorator(value) return type.__new__(cls, name, bases, local) class myClass(object): __metaclass__ = myMetaClass def baz(self): print self.baz.foo
它的作用就像myClass
每个可调用已经用myDecorator
装饰了myDecorator
>>> quux = myClass() >>> quux.baz() bar
不要从死里复活,但我真的很喜欢delnan的回答,但是发现它缺乏。
def for_all_methods(exclude, decorator): def decorate(cls): for attr in cls.__dict__: if callable(getattr(cls, attr)) and attr not in exclude: setattr(cls, attr, decorator(getattr(cls, attr))) return cls return decorate
编辑:修复缩进
所以你可以指定方法//属性//你不想装饰的东西
上面的答案都不适用于我,因为我也想修饰inheritance的方法,这不是通过使用__dict__
来完成的,我也不想用元类过分复杂化。 最后,我有一个Python 2的解决scheme,因为我只是立即需要添加一些分析代码来测量一个类的所有function使用的时间。
import inspect def for_all_methods(decorator): def decorate(cls): for name, fn in inspect.getmembers(cls, inspect.ismethod): setattr(cls, name, decorator(fn)) return cls return decorate
来源(略有不同的解决scheme): https : //stackoverflow.com/a/3467879/1243926在那里你也可以看到如何改变它的Python 3。
作为其他答案的build议,请考虑使用inspect.getmembers(cls, inspect.isroutine)
。 如果您已经find适用于Python 2和Python 3的适当解决scheme并且修饰了inheritance的方法,并且仍然可以在7行中完成,请编辑。
你可以生成一个元类。 这不会修饰inheritance的方法。
def decorating_meta(decorator): class DecoratingMetaclass(type): def __new__(self, class_name, bases, namespace): for key, value in list(namespace.items()): if callable(value): namespace[key] = decorator(value) return type.__new__(self, class_name, bases, namespace) return DecoratingMetaclass
这将生成一个元类,用所指定的函数装饰所有方法。 你可以在Python 2或3中使用它
def doubling_decorator(f): def decorated(*a, **kw): return f(*a, **kw) * 2 return decorated class Foo(dict): __metaclass__ = decorating_meta(doubling_decorator) def lookup(self, key): return self[key] d = Foo() d["bar"] = 5 print(d.lookup("bar")) # prints 10