1

I am currently working on a class decorator in Python for my example class. Below is the code containing the original class, the class decorator, and the class containing the function decorators. This code compiles and works as desired. I have omitted some functions from the example class for brevity.

def class_decorator(*method_names):
    def class_rebuilder(cls):    
        class NewClass(cls):        
            def __getattribute__(self, attr_name):            
                obj = super(NewClass, self).__getattribute__(attr_name)
                if (hasattr(obj, '__call__') and (attr_name in method_names)):                
                    if (attr_name == 'function1'):                    
                        return example_ClassDecorator().function1_decorator(obj)      
                    ...                              
                return obj
        return NewClass
    return class_rebuilder

class example_ClassDecorator():
    @classmethod
    def function1_decorator(cls, example_function1):    
        def decorator(*args ,**kwargs):        
            print ('Inside the decorator for function1 with args: ', args)
            return example_function1(*args , **kwargs)
        return decorator  
    ...

@class_decorator('function1',...)
class example(object):
    def __init__(self):    
        pass
    def function1(self, arg1):    
        print ('I am in example function1 with arg: ', arg1)
        if (arg1 == 'test'):        
            print 'testing'
    ...

I arrived at this code through research as to how to decorate methods and classes and python. As mentioned before, this code works. My issue is that I don't entirely understand the logic of what is going on.

Here is my current understanding of the code:

  1. I know that the @class_decorator('function1','function2',...) tag above the example class tells python that the given functions for this class are to be decorated. These strings are the *method_names passed into the class_decorator function.
  2. class_decorator then calls its class_rebuilder(cls) function which returns the class NewClass(cls) which will contain the newly decorator functions

  3. NewClass then calls __getattribute__(self, attr_name). obj is used to save the (function) object passed in.

  4. if (hasattr(obj, '__call__') and (attr_name in method_names)): confirms that obj is a function (by making sure it has the __call__ attribute associated with all function objects) and that it is one of the functions to be decorated.

  5. A series of if statements decides which function decorator to be called from the example_ClassDecorator function.

The class_decorator definition is where most of my questions lie.

  • How is class_rebuilder function called? Does python call it itself?
  • What populates the attr_name parameter in __getattribute__ method?
  • This line: obj = super(NewClass,self).__getattribute__(attr_name) It appears to be saving the named attribute object so as to check that it is a function. But I don't understand what is going on with the super call.

Any help explaining this code or a more prefered method to decorate classes in python would be greatly appreciated.

  • I'd suggest reading [data-model](https://docs.python.org/2/reference/datamodel.html) and [super() considered super!](https://rhettinger.wordpress.com/2011/05/26/super-considered-super/). And `@class_decorator('function1',...) class example(object):` is just a syntactic sugar for writing `example = class_decorator('function1')(example)`. Read: http://stackoverflow.com/a/1594484/846892. Basically your question is a duplicate of several other questions but you've asked too many. :-) – Ashwini Chaudhary Mar 18 '15 at 17:58
  • 1. `class_decorator`, followed by the resulting `class_builder`, is called by python in order to obtain a new class and replace `example` with it. Not having to write out this call explicitly is pretty much the entire value of decorators. 2. http://i.imgur.com/KuYnnCS.gif. This is a [magic method](http://www.rafekettler.com/magicmethods.html): `__getattribute__` is invoked with the name of an accessed whenever you access an attribute on an instance of the class. 3. That line and the following `if` are trying to intercept all access to a function in the base class. – Asad Saeeduddin Mar 18 '15 at 18:10

0 Answers0