[Python-Dev] LOAD_NAME & classes
Guido van Rossum
guido@python.org
Mon, 22 Apr 2002 14:15:51 -0400
> There's a bug report on SF that notes there is a difference between:
>
> def f(x):
> class Foo:
> x = x
>
> and
>
> x = 1
> class Foo:
> x = x
>
> The latter works because the class namespace uses LOAD_NAME and finds
> a global binding for x. The fact that x is also a local is invisible
> to LOAD_NAME.
>
> The former fails because x is none of locals, globals, or builtins,
> although it is bound in an enclosing scope. LOAD_NAME knows nothing
> about free variables, however, so it just blows up.
>
> Do we want to do anything about this apparent inconsistency?
>
> LOAD_NAME is obviously necessary to make stuff like exec work at all,
> and after a recent bug fix, it evens works as documented for nested
> scopes. But the docs for a class namespace (there aren't any, right?)
> don't suggest there is anything special going on.
>
> I imagine it would be possible to stop using LOAD_NAME for classes,
> but I'm not sure if that's a good thing. It could presumably break
> code that relies on LOAD_NAME's old fashioned search. It also seems
> like a non trivial amount of work because we'd need a new LOAD/STORE
> combo that only searched a locals dict. (Maybe that's not so hard.)
>
> I think module namespaces also use LOAD_NAME, but it's not clear why.
> Isn't a module's locals the same as its globals? If so, LOAD_GLOBAL
> could be used for all names.
>
> Any opinion on whether this is worth fixing? And is it a bug fix or a
> new feature?
I just tried this in 2.1 (without nested scopes enabled) and there the
first example fails too. While it's slightly confusing, it's
consistent with the rule that class bodies don't play the nested
scopes game, and I think it shouldn't be fixed. Otherwise you'd have
the confusing issue that a function inside a class can't see the class
scope, but a class inside a function can see the function scope.
Better if neither can see the other.
--Guido van Rossum (home page: http://www.python.org/~guido/)