Decorator Dissection
Ron_Adam
radam2 at tampabay.rr.com
Sat Apr 2 15:34:21 EST 2005
On Sat, 02 Apr 2005 21:04:57 +0200, "Diez B. Roggisch"
<deetsNOSPAM at web.de> wrote:
>> 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 :)
It's magic until we understand it. ;)
I get the feeling that those who have gotten to know decorators find
them easy, and those who haven't, find them nearly impossible to
understand. Which means there is a fairly large first few steps to
get over, then it gets easy. There *is* some underlying processes
being made, which is also the reason that makes them attractive. Less
type/declare/organize/etc... but that is also what causes the
difficulty in understanding and using them at first.
>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
This much I understand.
>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.
This tells me what it is, and what it does, but not how it works. How
is the ***expression evaluated***, what is the ***decorator
protocol***.
Those are the parts I'm trying to understand at this point. I know
this is the equivalent of looking behind the curtains to reveal the
little man who is the wizard. But I can't resist. :)
>So if you want to have _parametrized_ decorators, that expression is
>_evaluated_ and has to yield a decorator. Like this:
>
There's that word again... **evaluated**. How?
>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.
>
So if I'm following you right?
When the interpreter gets to the line @arge_decorator('fooobar')
it does the following?
foo = arg_decorator('fooobar')(foo)() #?
(experiment with idle a bit...)
Ok I got it. :)
I wasn't aware that the form:
result = function(args)(args)
Was a legal python statement.
So python has a built in mechanism for passing multiple argument sets
to nested defined functions! (click) Which means this is a decorator
without the decorator syntax.
def arg_decorator(arg1):
def real_decorator(function):
def wrapper(arg2)
return f(arg2)
return real_decorator
def foo(arg2):
pass
foo = arg_decorator('fooobar')(foo)(2arg)
The apparent magic is the silent passing of the second two arguments.
So this isn't a decorator question any more. Each argument gets
passed to the next inner defined function, via... a stack(?) ;)
Somehow I think I've completed a circle. LOL
Cheers,
Ron
>HTH - bit me the first time too :)
More information about the Python-list
mailing list