Slightly modifying the answer from Applying python decorators to methods in a class, it is possible to apply a decorator to every method in a class. Is there any way to do this without the inspect module? I've been trying to accomplish this using metaclasses and modifying __getattribute__ but I keep getting infinite recursion. From How is the __getattribute__ method used?, this can be fixed in normal classes using object.__getattribute__(self, name). Is there anything equivalent for metaclasses?
            Asked
            
        
        
            Active
            
        
            Viewed 1,553 times
        
    1 Answers
3
            Define a meta class and then just apply decorator at the end of class definition.
class Classname:
   def foo(self): pass
for name, fn in inspect.getmembers(Classname):
    if isinstance(fn, types.UnboundMethodType):
        setattr(Classname, name, decorator(fn))
For Python 3 just replace the types.UnboundMethodType with types.FunctionType.
but if you really don;t wanna use inspect than you can do it like this
import types
class DecoMeta(type):
   def __new__(cls, name, bases, attrs):
      for attr_name, attr_value in attrs.iteritems():
         if isinstance(attr_value, types.FunctionType):
            attrs[attr_name] = cls.deco(attr_value)
      return super(DecoMeta, cls).__new__(cls, name, bases, attrs)
   @classmethod
   def deco(cls, func):
      def wrapper(*args, **kwargs):
         print "before",func.func_name
         func(*args, **kwargs)
         print "after",func.func_name
      return wrapper
class MyKlass(object):
   __metaclass__ = DecoMeta
   def func1(self): 
      pass
MyKlass().func1()
Output:
before func1
after func1
Note: it will not decorate staticmethod and classmethod
 
    
    
        NIlesh Sharma
        
- 5,445
- 6
- 36
- 53
- 
                    are you sure it won't decorate staticmethod? because after asking this question I discovered \_\_new\_\_ and wrote something very similar where staticmethod worked. – weeb Aug 09 '12 at 21:43
 
    