[Python-ideas] Tweaking closures and lexical scoping to include the function being defined

Stephen J. Turnbull stephen at xemacs.org
Sat Oct 1 20:57:19 CEST 2011


Ron Adam writes:

 > Supposedly the @ decorator syntax is supposed to be like a pre-compile
 > substitution where..
 > 
 >     @decorator
 >     def func(x):x
 > 
 > Is equivalent to...
 > 
 >     def func(x):x
 >     func = decorator(func)
 > 
 > IF that is true,

It is.

 > it doesn't make the python core more complex. It would
 > just be a source rewrite of the effected block in memory just before
 > it's compiled.
 > 
 > But it seems it's not implemented exactly that way.
 > 
 > def deco(func):
 >     def _(f):
 >         return func(f)
 >     return _
 > 
 > @deco(foo)
 > def foo(f):
 >     return f
 > 
 > print(foo('python'))
 > 
 > Results with ... NameError: name 'foo' is not defined

This is different syntax, whose interpretation is not obvious from the
simpler case.  For example, by analogy to method syntax it could mean

def foo(f):
    return f
foo = deco(foo, foo)

(where the first argument is implicit in the decorator syntax = the
function being decorated, and the second is the explicit argument), in
which case you would have gotten a "too few arguments" error instead,
but it's doesn't.  In fact, it is defined to be equivalent to

bar = deco(foo)
@bar
def foo(f):
    return f

Ie,

bar = deco(foo)
def foo(f):
    return foo
foo = bar(foo)

(which makes the reason for the error obvious), not

 > def foo(f):
 >     return f
 > foo = deco(foo)

I guess in theory you could think of moving the evaluation of
deco(foo) after the def foo, but then the correct equivalent
expression would be

def foo(f):
    return f
foo = deco(foo)(foo)

which I suspect is likely to produce surprising behavior in many
cases.





More information about the Python-ideas mailing list