On Sat, 02 Apr 2005 21:04:57 +0200, "Diez B. Roggisch" <[EMAIL PROTECTED]> 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 :) -- http://mail.python.org/mailman/listinfo/python-list