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

Ron Adam ron3200 at gmail.com
Sat Oct 1 18:58:21 CEST 2011


On Sat, 2011-10-01 at 13:44 +0200, Jan Kaliszewski wrote:
> Jan Kaliszewski dixit (2011-09-30, 23:32):
> 
> > Nick Coghlan dixit (2011-09-30, 14:14):
> > 
> > > If a "function state decorator" approach is used, then yeah, I agree
> > > it should come immediately before the main part of the function
> > > header.
> > 
> > Yes, it seems to be a necessary requirement.
> > 
> > > However, I'm not seeing a lot to recommend that kind of syntax
> > > over the post-arguments '[]' approach.
> > 
> > IMHO @(...) has two advantages over '[]' approach:
> > 
> > 1. It keeps all that 'additional scope'-stuff in a separate line, making
> > the code probably more clear visualy, and not making the crowd of
> > elements in the '...):' line even more dense (especially if we did use
> > annotations, e.g.: '...) -> "my annotation":').
> > 
> > 2. It is more consistent with the existing syntax (not introducing
> > '='-based syntax within []; [] are already used for two different
> > things: list literals and item lookup -- both somehow leading your
> > thoughts to sequence/container-related stuff).
> 
> And also -- what maybe is even more important --
> 
> 3. Placing it before (and beyond) the whole def statement makes it
> easier to *explain* the syntax:
> 
>     @(x=1, lock=Lock())
>     def do_foo(y):
>         nonlocal x
>         with lock:
>             x += y
>         return x

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 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


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

print(foo('python'))

Prints "Python" and doesn't cause a name error.
Is this a bug, or by design?


I thought, if the @@ wrapper idea could be put in terms of a simple
substitution template like the @ design, then it may be more doable.

Cheers,
   Ron



> as being equivalent to:
> 
>     def _closure_provider():
>         x = 1
>         lock = Lock()
>         def do_foo(y):
>             nonlocal x
>             with lock:
>                 x += y
>             return x
>         return do_foo
>     do_foo = _closure_provider()
>     del _closure_provider






More information about the Python-ideas mailing list