[Python-Dev] nested scopes. global: have I got it right?

Tim Peters tim.one@home.com
Wed, 28 Feb 2001 21:11:25 -0500


[Samuele Pedroni]
> x=7
> def f():
>   global x
>   def g():
>     exec "x=3"
>     return x
>   print g()
>
> f()
>
> prints 3, not 7.

Note the the Ref Man (section on the global stmt) adds some more wrinkles:

    ...
    global is a directive to the parser.  It applies only to code
    parsed at the same time as the global statement.  In particular,
    a global statement contained in an exec statement does not
    affect the code block containing the exec statement, and code
    contained in an exec statement is unaffected by global statements
    in the code containing the exec statement.  The same applies to the
    eval(), execfile() and compile() functions.

>From that we deduce that the x in "x=3" can't refer to the global x no matter
what.  Therefore it must refer to a local x.  Therefore the x in "return x"
must also refer to a local x, lest the single name x refer to two distinct
vrbls in the body of g.

This was mind-twisting even before nested scopes, though:

>>> x = 666
>>> def f():
...     global x
...     exec("x=3")  # still doesn't "see" the global above it
...     print x
...
>>> f()
666
>>>

So to what did the x in "x=3" refer *there*?  Must have been different than
the x in "print x"!

Mixing global, import*, and exec has always been a rich source of surprises.

Again with a twist:

>>> x = 666
>>> def f():
...     global x
...     exec "global x\nx = 3\n"
...     print x
...
>>> f()
<string>:0: SyntaxWarning: global statement has no meaning at module level
3
>>>

Now it's consistent.  But the warning is pretty mysterious!  The 'global' in
the string passed to exec has a crucial meaning.