Preet Sangha Preet Sangha - 3 months ago 8
Python Question

How does this python decorator work?

Edit/Clarification to make my question specific to my query:
*I can see how the decorator static log function is called but I don't see how _ is called and how the result of it is the result of log. I cam see how the entry/enter stuff works*

class logger:
@staticmethod
def log(func):
def ___(*args, **kwargs):
try:
print "Entering: [%s] with parameters %s" % (func.__name__, args)
try:
return func(*args, **kwargs)
except Exception, e:
print 'Exception in %s : %s' % (func.__name__, e)
finally:
print "Exiting: [%s]" % func.__name__
return ___


class x:
@logger.log
def first_x_method(self):
print 'doing first_x_method stuff...'

x().first_x_method()


gives this output:

Entering: [first_x_method] with parameters (<__main__.x instance at 0x0000000001F45648>,)
doing first_x_method stuff...
Exiting: [first_x_method]


I can see that logger is a class with a static method that is used to decorate (
@logger.log
) first_x_method.

However I don't understand why the
___
sub method (and it can be any name) is called.

Answer

The fundamental fact about decorators is that

@decorator
def func(): ...    

is exactly equivalent to

def func(): ...
func=decorator(func)

So,

@logger.log
def first_x_method(self): ...

is the same as

def first_x_method(self): ...
first_x_method=logger.log(first_x_method)

and so the logger.log static method is called with argument func = first_x_method.

Inside the call to logger.log(first_x_method), the sub method __ is defined and returned.

first_x_method=logger.log(first_x_method) thus sets first_x_method to refer to the sub method __.

The parenthesis in first_x_method() tells Python to call the method first_x_method.

So x().first_x_method() first instantiates an instance of the class x, and then calls the method first_x_method (with x() supplied as the first argument).

Since first_x_method refers to __, it is __ that gets called.