[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!