[Python-3000] Draft PEP for outer scopes

Talin talin at acm.org
Thu Nov 2 10:42:57 CET 2006

Fredrik Lundh wrote:
> Steven Bethard wrote:
>> I don't think that'll really be worth it.  I'd be amazed if people
>> didn't expect it to mean "top-level".
> as anyone who's spent enough time on c.l.python knows, people expect it 
> to mean "application global".  it isn't.
> alternatively, they expect it to be a scope specifier to be used when 
> creating the variable, rather than when referring to it.  it isn't.
> the exact meaning of "global" is one of the well-known "you only need to 
> learn this once" things in Python.  a reinterpreted global would fall in 
> the same category.

One thing I don't understand in this discussion of re-purposing the 
'global' keyword is how you handle the case of an inner function that 
*creates* a global.

Right now, you can create a global variable from within a scope, even if 
that variable hasn't been declared yet:

    def foo():
       global x
       x = 1

    print x

However, if 'global' is simply a synonym for 'nonlocal', then how does 
it know *which* scope to create the variable in?

Let me anticipate one possible answer: "Don't do that". My response 
would be: first, being able to do that is occasionally useful, and 
second, if we can't do it, then we're back to the notion that global 
variables have to be "declared" before they can be used in inner 
functions...not exactly within the theme of Python.

However, it just occurred to me that there's another option, one that's 
not yet included in Ping's PEP: _Named Lexical Scopes_.

What if 'global' was not a keyword, but rather a name? So when you say 
"global x" you really mean that 'x' derives from a lexical scope that 
has the name 'global'.

Inner scopes would be named after the function that defines the scope. 
So for example:

    def foo():
       def bar():
          foo x    # means that 'x' is defined in the 'foo' scope
          x = 1

       print x

Admittedly, using a bare non-keyword identifier is probably a bit too 
tricky in terms of parsing; Sure, it could be done, but its likely that 
it might create some parsing ambiguities that might bite us down the 
road. So I'd say go ahead and use a keyword to introduce a reference to 
a named scope, for example:

    def outer():
       def inner1():
          def inner2():
             scope inner1 x, y = 1, 2
             scope outer z = 3
             scope global a = "this is a test"

This syntax allows us to refer to any arbitrary outer scope, regardless 
of whether a local variable has been defined in that scope or not. Its 
also immune to variables changing meaning if the hierarchy of scopes is 
rearranged - for example, if we remove 'inner2' from inside 'inner1', 
the the references to 'outer' and 'global' still mean exactly the same 
thing as they did before.

Also, this scheme does not prevent the compiler from knowing at compile 
time exactly what local variables are defined in which scopes.

-- Talin

More information about the Python-3000 mailing list