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

Guido van Rossum guido at python.org
Tue Sep 27 03:32:19 CEST 2011

Interesting discussion! Very enlightening.

But after all that I'm still unconvinced that the new concept should
be tied to the nonlocal keyword.

Nick's right that the *mechanism* for nonlocals and __class__ is the
same, and the mechanism for the new concept might well be the same.
And possibly a hypothetical other Python implementation could use the
same mechanism to keep track of default argument values. Or not.

But at a different level, nonlocal and the new concept are quite
different, and the difference has to do with the scope of the name,
not its lifetime (this was a very important insight in the
discussion!). I think it is actually very telling that the syntax for
nonlocal, __class__ and default argument values is so different: to
most users, the lifetime is much less of an issue than the scope.

Now, let's pretend the new feature is called "own". We'd write:

def counter():
  own x = 0
  x += 1
  return x

If we had another function (say, defined in the same scope):

def count_by_twos():
  own x = 0
  x += 2
  return x

the x in counter() and count_by_twos() are unrelated. This is
different from the way nonlocal works (I don't have to type the
example I hope :-). Also, nonlocal is illegal in a global function --
syntactically, it must be in a function that is nested inside another

For all these reasons, sorry Nick, but I really don't think any syntax
based on nonlocal will do it, even "nonlocal <var> from <expr>".

I see two options open at this point.

1) Bikeshed until we've come up with the right keyword. I think that
apart from the keyword the optimal syntax is entirely fixed;
"<keyword> <variable> = <expression>" is the way to go. (I suppose we
could argue about how to declare multiple variables this way.) I would
be okay with using either "static" or "own" for the keyword.
Personally, I don't really mind all the negative baggage that static
has, but a Google code search for \bown\s= shows way fewer hits than
for \bstatic\s= (both with lang:^python$ case:yes).

2) Give up, and keep using the default argument hack. You can protect
your arguments from accidentally being overridden by using a "lone
star" in the argument list (PEP 3102) and a __private naming
convention. The lone star prevents accidental overriding when too many
positional arguments are given. The __private provides sufficient
protection against misguided attempts to provide a value for such
"arguments", even if for functions outside a class it is purely
psychological. (Note that someone who *really* wanted to mess with a
cell's variable could also do it.)

--Guido van Rossum (python.org/~guido)

More information about the Python-ideas mailing list