How to decorate all the functions of a class without typing it again and again for each method?

Suppose there are many methods in my class and I want to apply my decorator to each of them, later, when I add new methods, I want to apply the same decorator, but I don’t want to write @mydecorator over the time method declaration?

If I __call__ in __call__ , is this the right way?

IMPORTANT: the example below seems to solve a problem other than the original question.

EDIT: I would like to show this path, which is a similar solution to my problem for anyone who does not find 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__: return super(Wrapmymethodsaround, self).__call__(hey, you, *args) 
+44
python decorator wrapper
Jun 10 2018-11-11T00:
source share
5 answers

Decorate the class with a function that goes through the class attributes and decorates the calls. This may not be the right task if you have class variables that can be called and also decorate nested classes (loans to Sven Marnach for pointing this out), but overall this is a pretty clean and simple solution. Implementation example (note that this does not exclude special methods ( __init__ , etc.) that may or may not be desirable):

 def for_all_methods(decorator): def decorate(cls): for attr in cls.__dict__: # there propably a better way to do this if callable(getattr(cls, attr)): setattr(cls, attr, decorator(getattr(cls, attr))) return cls return decorate 

Use this:

 @for_all_methods(mydecorator) class C(object): def m1(self): pass def m2(self, x): pass ... 

In Python 3.0 and 3.1, callable does not exist. It has existed since forever in Python 2.x and returned to Python 3.2 as a wrapper for isinstance(x, collections.Callable) , so you can use this (or define your own callable replacement using this) in these versions.

+48
Jun 10 2018-11-11T00:
source share

Although I do not like to use magic approaches with an explicit approach, perhaps you can use a metaclass to do this.

 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 

and works as if every caller in myClass was decorated with myDecorator

 >>> quux = myClass() >>> quux.baz() bar 
+24
Jun 10 2018-11-11T00:
source share

Not to raise things from the dead, but I really liked the delnan answer, but found that sllliigghhtttlllyy was missing.

 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 

EDIT: fix indentation

So, you can specify methods // attributes // material that you do not want to style

+7
Jan 31 '12 at 10:01
source share

None of the above answers worked for me, since I also wanted to decorate the inherited methods, which was not achieved with __dict__ , and I did not want to recombine things with metaclasses. Finally, I am doing a great job with the solution for Python 2, since I just need to add some profiling code to measure the time used by all the functions of the class.

 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 

Source (a slightly different solution): https://stackoverflow.com/a/4646262/2326328/2326322#6129298

As the comments to other answers inspect.getmembers(cls, inspect.isroutine) , use inspect.getmembers(cls, inspect.isroutine) . If you find the right solution that works for both Python 2 and Python 3 and embellishes inherited methods, and can still be done in 7 lines, please edit.

+3
Jun 10 '15 at 18:47
source share

You can create a metaclass. This will not beautify inherited methods.

 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 

This will create a metaclass that adorns all methods with the specified function. You can use it in Python 2 or 3 by doing something like this

 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 
+2
Jun 10 2018-11-11T00:
source share



All Articles