[Python-Dev] Re: closure semantics

Alex Martelli aleaxit at yahoo.com
Sat Oct 25 04:07:36 EDT 2003

On Friday 24 October 2003 23:32, Guido van Rossum wrote:
> or at run-time) always goes from inner scope to outer.  While you and
> I see nested functions as small amounts of closely-knit code, some
> people will go overboard and write functions of hundred lines long
> containing dozens of inner functions, which may be categorized into

This doesn't look like a legitimate use case to me; i.e., I see no need
to distort the language if the benefit goes to such "way overboard" uses.
I think they will have serious maintainability problems anyway.

Fortunately, I don't think of placing the "indication to the compiler" as
close to the assignment-to-outer-variable as a distortion;-)

> Anyway, I hope you'll have a look at my reasons for why the compiler
> needs to know about rebinding variables in outer scopes from inside
> an inner scope.

Sure!  I do understand this.  What I don't understand is why, syntactically,
the reserved word that indicates this to the compiler should have to be
a "statement that does nothing" -- the ONLY "declaration" in the language --
rather than e.g. an _operator_ which specifically flags such uses.

Assume for the sake of argument that we could make 'scope' a reserved
word.  Now, what are the tradeoffs of using a "declaration"
    scope x in outer
which makes all rebidings of x act in the scope of containing function
outer (including 'def x():', 'class x:', 'import x', ...); versus an 
"operator" that must be used to indicate "which x" when specifically
assigning it (no "side effect rebinding" via def &c allowed -- I think it
helps the reader of code a LOT to require specific assignment!), e.g.
    scope(outer).x = 23

Don't think of scope as a built-in function, but as a keyword in either
case (and we could surely have other syntax for the "scope operator",
e.g. "(x in outer scope) = 23" or whatever, as long as it's RIGHT THERE
where x is being assigned).  So the compiler can catch on to the info
just as effectively.

The tradeoffs are:
   -- we can keep thinking of Python as declaration-free and by gradually
       deprecating the global statement make it more so
   -- the reader of code KNOWS what's being assigned to without having
       to scroll up "hundreds of lines" looking for possible declarations
   -- assignment to nonlocals is made less casually convenient by just the
       right amount to ensure it won't be overused
   -- no casual rebinding of nonlocals via def, class, import
   -- once we solve the general problem of allowing non-bare-names as
       iteration variables in 'for', nonlocals benefit from that resolution
       automatically, since nonlocals are never assigned-to as bare-names

I see this as the pluses.  The minus is, we need a new keyword; but I
think we do, because stretching 'global' to mean something that ISN'T
global in any sense is such a hack.

Cutting both ways is the fact that this allows using the same name from
more than one scope (since each use is explicitly qualified as coming
from a specific scope).  That's irrelevant for small compact uses of
nesting, but it may be seen as offering aid and succour to those wanting
to "go overboard" as you detail earlier (bad); OTOH, if I ever need to
maintain such "overboard" code written by others, and refactoring it is
not feasible right now, it may be helpful.  In any case, the confusion is
reduced by having the explicit qualification on assignment.  Similarly
for _accesses_ rather than rebindings -- access to the barename will
keep using the same rules as today, of course, but I think the same syntax
that MUST be used to assign nonlocals should also be optionally usable
to access them -- not important either way in small compact functions,
but more regular and offering a way to make code non-ambiguous in large
I don't see having two ways to access a name -- barename x or qualified
scope(foo).x -- as a problem, just like today from inside a method we may
access a classvariable as "self.x" OR "self.__class__.x" indifferently -- 
the second form is needed for rebinding and may be chosen for clarity
in some cases where the first simpler ("barer") one would suffice.


More information about the Python-Dev mailing list