Writing a class decorator that applies a decorator to all methods
我正在尝试编写一个类修饰器,它将修饰器应用于所有类的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | import inspect def decorate_func(func): def wrapper(*args, **kwargs): print"before" ret = func(*args, **kwargs) print"after" return ret for attr in"__module__","__name__","__doc__": setattr(wrapper, attr, getattr(func, attr)) return wrapper def decorate_class(cls): for name, meth in inspect.getmembers(cls, inspect.ismethod): setattr(cls, name, decorate_func(meth)) return cls @decorate_class class MyClass(object): def __init__(self): self.a = 10 print"__init__" def foo(self): print self.a @staticmethod def baz(): print"baz" @classmethod def bar(cls): print"bar" obj = MyClass() obj.foo() obj.baz() MyClass.baz() obj.bar() MyClass.bar() |
它几乎可以工作,但
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | $ python test.py before __init__ after before 10 after baz baz before Traceback (most recent call last): File"test.py", line 44, in <module> obj.bar() File"test.py", line 7, in wrapper ret = func(*args, **kwargs) TypeError: bar() takes exactly 1 argument (2 given) |
号
有没有办法很好地处理这个问题?我检查了
更新
这里是记录的完整解决方案(使用描述符很好地处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | import inspect class DecoratedMethod(object): def __init__(self, func): self.func = func def __get__(self, obj, cls=None): def wrapper(*args, **kwargs): print"before" ret = self.func(obj, *args, **kwargs) print"after" return ret for attr in"__module__","__name__","__doc__": setattr(wrapper, attr, getattr(self.func, attr)) return wrapper class DecoratedClassMethod(object): def __init__(self, func): self.func = func def __get__(self, obj, cls=None): def wrapper(*args, **kwargs): print"before" ret = self.func(*args, **kwargs) print"after" return ret for attr in"__module__","__name__","__doc__": setattr(wrapper, attr, getattr(self.func, attr)) return wrapper def decorate_class(cls): for name, meth in inspect.getmembers(cls): if inspect.ismethod(meth): if inspect.isclass(meth.im_self): # meth is a classmethod setattr(cls, name, DecoratedClassMethod(meth)) else: # meth is a regular method setattr(cls, name, DecoratedMethod(meth)) elif inspect.isfunction(meth): # meth is a staticmethod setattr(cls, name, DecoratedClassMethod(meth)) return cls @decorate_class class MyClass(object): def __init__(self): self.a = 10 print"__init__" def foo(self): print self.a @staticmethod def baz(): print"baz" @classmethod def bar(cls): print"bar" obj = MyClass() obj.foo() obj.baz() MyClass.baz() obj.bar() MyClass.bar() |
(P)EDOCX1(音译)0应该告诉你,字母名称1是一种古典方法:(p)字母名称
(P)(一个评论太长了)(p)(P)I took the liberty of adding the ability to specify which methods should get designated to your solution:(p)字母名称(P)USAGE:(p)字母名称
(P)The above answers do not apply directly to pyton3.Based on the other great answers I have been able to come up with the following solution:(p)字母名称(P)Now anytime a method in the tuple EDOCX1 English 2 is called,the Dirty Flag is set.of course,anything else can be put there too.它不需要将EDOCX1的英文本3分类包括在类别中,因为所有方法都需要被超越。然而,作为EDOCX1的一个英文字母4,使用了特殊的符号来表示阶级,我倾向于使一个阶级有意义。(p)