How to decorate all functions of a class without typing it over and over for each method? [duplicate] How to decorate all functions of a class without typing it over and over for each method? [duplicate] python python

How to decorate all functions of a class without typing it over and over for each method? [duplicate]


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):

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

Use like 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 existed since forever in Python 2.x and is back in Python 3.2 as wrapper for isinstance(x, collections.Callable), so you can use that (or define your own callable replacement using this) in those versions.


While I'm not fond of using magical approaches when an explicit approach would do, you can probably use a metaclass for this.

def myDecorator(fn):    fn.foo = 'bar'    return fnclass 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 it works as though each callable in myClass had been decorated with myDecorator

>>> quux = myClass()>>> quux.baz()bar


Not to revive things from the dead, but I really liked delnan's answer, but found it sllliigghhtttlllyy lacking.

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 indenting

So you can specify methods//attributes//stuff you don't want decorated