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

Ron Adam ron3200 at gmail.com
Sun Oct 2 08:29:35 CEST 2011

On Sat, 2011-10-01 at 22:11 -0400, Nick Coghlan wrote:

+1 on all of the zen statements of course.

I think you made a fine case for being careful and mindful about this
stuff.  :-)

> Namespaces are one honking great idea -- let's do more of those!
>   - closures are just another form of namespace, even though people
> typically think of classes, modules and packages when contemplating
> this precept. "Function state variables" would be formalising the
> namespace where default argument values live (albeit anonymously) and
> making it available for programmatic use.

One way to think of this is, Private, Shared, and Public, name spaces.
Private and Public  are locals and globals, and are pretty well
supported, but Shared names spaces, (closures or otherwise) are not well

I think the whole concept of explicit shared name spaces, separate from
globals and locals is quite important and should be done carefully.  I
don't think it is just about one or two use-cases that a small tweak
will cover.

> Despite its flaws, the simple brackets enclosed list after the
> function parameter list is still my current favourite:
>     def global_counter(x) [n=0, lock=Lock()]:
>         with lock:
>             n += 1
>             yield n
> It just composes more nicely with decorators than the main alternative
> still standing and is less prone to overwhelming the function name
> with extraneous implementation details:

This syntax to me looks a bit too close to a list literal.  

How about a name space literal? ie.. a dictionary.

    def global_counter(x) {n:0, lock=lock}:
        with lock:
            n += 1
            yield n

I think that looks better than dict(n=0, lock=lock).  And when used as a
repr for name spaces, it is more readable.

A literal would cover the default values use case quite nicely.  A
reference to a pre-defined dictionary would cover values shared between
different functions independent of scope.

>     @contextmanager
>     def counted()  [active=collections.Counter(),
>  lock=threading.RLock()]:

> far more clearly conveys "this defines a context manager named
> 'counted'" than the following does:

>     @contextmanager
>     @(active=collections.Counter(), lock=threading.RLock())
>     def counted():

Putting them after the function signature will result in more wrapped
function signatures.

While its very interesting to try to find a solution, I am also
concerned about what this might mean in the long term.  Particularly we
will see more meta programming.  Being able to initiate an object from
one or more other objects can be very nice.  Python does that sort of
thing all over the place.



More information about the Python-ideas mailing list