如何装饰类的所有函数,而无需为每个方法一遍又一遍地键入它?
假设我的类有很多方法,我想在每个方法上应用我的装饰器,稍后当我添加新方法时,我希望应用相同的装饰器,但我不想写 @mydecorator 始终位于方法声明上方。
如果我查看 __call__
这是正确的方法吗?
我想展示这种方式,对于后来发现这个问题的任何人来说,这是与我的问题类似的解决方案,使用评论中提到的混合。
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__(self, hey, you, *args):
return super(Wrapmymethodsaround, self).__call__(hey, you, *args)
编者注中:此示例似乎解决了与所询问的问题不同的问题。
Lets say my class has many methods, and I want to apply my decorator on each one of them, later when I add new methods, I want the same decorator to be applied, but I don't want to write @mydecorator
above the method declaration all the time.
If I look into __call__
is that the right way to go?
I'd like to show this way, which is a similar solution to my problem for anybody finding this question later, using a mixin as mentioned in the comments.
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)
Then you can in another
class Wrapmymethodsaround(WrapinMixin):
def __call__(self, hey, you, *args):
return super(Wrapmymethodsaround, self).__call__(hey, you, *args)
Editor's note: this example appears to be solving a different problem than what is asked about.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
使用遍历类的属性并装饰可调用对象的函数来装饰类。如果您的类变量可能是可调用的,并且还会装饰嵌套类(感谢 Sven Marnach 指出了这一点),那么这可能是错误的做法,但通常这是一个相当干净和简单的解决方案。示例实现(请注意,这不会排除特殊方法(
__init__
等),这可能是需要的,也可能不是):像这样使用:
Decorate the class with a function that walks through the class's attributes and decorates callables. This may be the wrong thing to do if you have class variables that may happen to be callable, and will also decorate nested classes (credits to Sven Marnach for pointing this out) but generally it's a rather clean and simple solution. Example implementation (note that this will not exclude special methods (
__init__
etc.), which may or may not be desired):Use like this:
虽然当显式方法可以时我不喜欢使用神奇的方法,但您可能可以为此使用元类。
它的工作原理就好像
myClass
中的每个可调用对象都用myDecorator
进行了装饰While I'm not fond of using magical approaches when an explicit approach would do, you can probably use a metaclass for this.
and it works as though each callable in
myClass
had been decorated withmyDecorator
不是为了死而复生,但我真的很喜欢德尔南的答案,但发现它缺乏。
编辑:修复缩进
所以你可以指定方法//属性//你不想装饰的东西
Not to revive things from the dead, but I really liked delnan's answer, but found it sllliigghhtttlllyy lacking.
EDIT: fix indenting
So you can specify methods//attributes//stuff you don't want decorated
上述答案都不适合我,因为我还想装饰继承的方法,这不是通过使用 __dict__ 来完成的,而且我不想使用元类使事情变得过于复杂。最后,我很乐意为 Python 2 提供一个解决方案,因为我只是立即需要添加一些分析代码来测量类的所有函数所使用的时间。
来源(略有不同的解决方案):https://stackoverflow.com/a/3467879/1243926
在那里,您还可以了解如何针对 Python 3 更改它。
正如对其他答案的评论所建议的那样,请考虑使用
inspect.getmembers(cls,spectr.isroutine)
代替。如果您找到了适用于 Python 2 和 Python 3 并装饰继承方法的正确解决方案,并且仍然可以在 7 行内完成,请编辑。None of the above answers worked for me, since I wanted to also decorate the inherited methods, which was not accomplished by using
__dict__
, and I did not want to overcomplicate things with metaclasses. Lastly, I am fine with having a solution for Python 2, since I just have an immediate need to add some profiling code for measuring time used by all functions of a class.Source (slightly different solution): https://stackoverflow.com/a/3467879/1243926
There you can also see how to change it for Python 3.
As comments to other answers suggest, consider using
inspect.getmembers(cls, inspect.isroutine)
instead. If you have found a proper solution that works for both Python 2 and Python 3 and decorates inherited methods, and can still be done in 7 lines, please, edit.您可以生成一个元类。这不会修饰继承的方法。
这将生成一个元类,用指定的函数装饰所有方法。您可以通过执行以下操作在 Python 2 或 3 中使用它
You could generate a metaclass. This will not decorate inherited methods.
This will generate a metaclass decorating all methods with the specified function. You can use it in Python 2 or 3 by doing something like this