[Python-Dev] nested scopes and global: some corner cases

Tim Peters tim.one@home.com
Sun, 11 Mar 2001 00:16:38 -0500


[Samuele Pedroni]
> ...
> I have tried them with python 2.1b1 and I wonder if the results
> are consistent with the proposed rule:
> a free variable is bound according to the nearest outer scope binding
> (assign-like or global decl),
> class scopes (for backw-comp) are ignored wrt this.

"exec" and "import*" always complicate everything, though.

> (I)
> from __future__ import nested_scopes
>
> x='top'
> def ta():
>  global x
>  def tata():
>   exec "x=1" in locals()
>   return x # LOAD_NAME
>  return tata
>
> print ta()() prints 1, I believed it should print 'top' and a
> LOAD_GLOBAL should have been produced.

I doubt this will change.  In the presence of exec, the compiler has no idea
what's local anymore, so it deliberately generates LOAD_NAME.  When Guido
says he intends to "deprecate" exec-without-in, he should also always say
"and also deprecate exec in locals()/global() too".  But he'll have to think
about that and get back to you <wink>.

Note that modifications to locals() already have undefined behavior
(according to the Ref Man), so exec-in-locals() is undefined too if the
exec'ed code tries to (re)bind any names.

> In this case the global binding is somehow ignored. Note: putting
> a global decl in tata xor removing the exec make tata deliver 'top' as
> I expected (LOAD_GLOBALs are emitted).
> Is this a bug or I'm missing something?

It's an accident either way (IMO), so it's a bug either way too -- or a
feature either way.  It's basically senseless!  What you're missing is the
layers of hackery in support of exec even before 2.1; this "give up on static
identification of locals entirely in the presence of exec" goes back many
years.

> (II)
> from __future__ import nested_scopes

> x='top'
> def ta():
>     x='ta'
>     class A:
>         global x
>         def tata(self):
>             return x # LOAD_GLOBAL
>     return A
>
> print ta()().tata() # -> 'top'
>
> should not the global decl in class scope be ignored and so x be
> bound to x in ta, resulting in 'ta' as output?

Yes, this one is clearly a bug.  Good catch!