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

Nick Coghlan ncoghlan at gmail.com
Thu Sep 29 21:48:55 CEST 2011


On Thu, Sep 29, 2011 at 3:03 PM, Eric Snow <ericsnowcurrently at gmail.com> wrote:
> Instead it could imply that the name should fall back to the
> definition-time "scope" of the current function.  In other words, the
> compiler would treat the name like a closed variable anyway, but with
> an empty cell (or some default initial value, like None).

Yeah, I'd thought of that possibility and have a few problems with it:

1. Replacing the current SyntaxError when a nonlocal statement refers
to a variable that doesn't exist in an outer scope with a call time
"UnboundNonLocalError" or an implicit None reference doesn't thrill
me. Either choice would make UnboundLocalError look positively
intuitive.

2. Adding a general ability to edit closure references from pure
Python code outside the function body is a bridge I'm highly reluctant
to cross. That kind of thing is what classes are for.

3. The syntax is repetitive and noisy enough that I think people could
be legitimately excused for continuing to use the default argument
hack instead. It's important to keep in mind that for folks that are
familiar with how it works, the default argument hack is actually
pretty easy to read and write. It's quite clearly exploiting a side
effect of a feature that was added for other reasons, though, which is
why blessing and documenting it as the preferred mechanism for
function state variables (if you choose to use them) also doesn't feel
right.

All that said, the @nonlocal idea certainly has its own problems. In
particular, it looks superficially like an ordinary call to a
decorator factory, but is actually quite restricted syntactically
(keyword arguments only, no * or ** expansion), has significant
effects on the resolution of names in the function's namespace and
can't be used for post-decoration via an ordinary function call with
the just defined function as an argument.

It would end up in the same category of "special case that doesn't
actually look all that special" as the 3.x version of super().

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia



More information about the Python-ideas mailing list