Decorator Dissection

Diez B. Roggisch deetsNOSPAM at web.de
Sat Apr 2 14:04:57 EST 2005


> I followed that part.  The part that I'm having problems with is the
> first nested function get's the argument for the function name without
> a previous reference to the argument name in the outer frames. So, a
> function call to it is being made with the function name as the
> argument, and that isn't visable so it looks as if it's magic.

No, its not - but I stepped into that trap before - and thought its magic :)

The trick is to know that

 - a decorator is a callable
 - get passed a callable
 - has to return a callable

So this is the simplest decorator imaginable is:

def identity(f):
    return f

And the decorator _syntax_ is just a python expression that has to be
_evaluated_ to a yield decorator. So

@identity
def foo(self):
    pass

the @identity is just the expression evaluated - to the function reference
to identity, which is callable and follows the decorator protocol - and the
_result_ of that evaluation is called with the callable in question.

So if you want to have _parametrized_ decorators, that expression is
_evaluated_ and has to yield a decorator. Like this:

def arg_decorator(arg):
    def real_decorator(f):
        return f
    return real_decorator

So, this works 

@arg_decorator('fooobar')
def foo(self):
    pass

@arg_decorator('fooobar') is evaluated to real_decorator (which a scope
containing arg), and _that_ gets called with foo.

HTH - bit me the first time too :)


-- 
Regards,

Diez B. Roggisch



More information about the Python-list mailing list