This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: NameError assigning to class in a func
Type: Stage:
Components: Interpreter Core Versions: Python 2.2
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: jhylton Nosy List: jhylton, spiv
Priority: normal Keywords:

Created on 2002-03-21 01:27 by spiv, last changed 2022-04-10 16:05 by admin. This issue is now closed.

Messages (5)
msg9853 - (view) Author: Andrew Bennetts (spiv) Date: 2002-03-21 01:27
This fails with a NameError:

def f(x)
    class Private:
        x = x
    return Private
f(17)

But this works:

def f(x):
    y = x
    class Private:
        x = y
    return Private
f(17)

But this fails:

def f(x):
    y = x
    class Private:
        y = y
    return Private
f(17)

See also the newsgroup thread:
http://groups.google.com/groups?hl=en&ie=ISO-8859-1&oe=ISO-8859-1&threadm=Xns

(All tested on Python 2.2 on Win2k)

msg9854 - (view) Author: Jeremy Hylton (jhylton) (Python triager) Date: 2002-04-19 16:39
Logged In: YES 
user_id=31392

This is actually working as intended, although the reference
manual no longer describes this case at all.  It has been a
long standing "feature" of Python that module and class
blocks use the LOAD_NAME opcode, which has weird scoping
rules.

The documentation should be updated to describe the cases in
which LOAD_NAME is used and its behavior.  (It checks
locals, globals, builtins in that order, and never raises a
NameError unless the name isn't found in any of those
namespaces.  In particular, an unbound local is simply
ignored.)

I don't actually know what these rules are used.  Guido--
should we get rid of LOAD_NAME?
msg9855 - (view) Author: Andrew Bennetts (spiv) Date: 2002-04-22 09:31
Logged In: YES 
user_id=50945

Apologies for re-opening the bug.

This behaviour still seems like a bug to me, because while
this dies:

>>> def f(x):
...     class Private:
...         x = x
...     return Private
... 
>>> f(17)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 2, in f
  File "<stdin>", line 3, in Private
NameError: name 'x' is not defined

This works:

>>> x = 1 
>>> class C:
...     x = x
... 
>>> C()
<__main__.C instance at 0x806aeac>

Actually, having the global "x = 1" also makes the first
case work.

This seems inconsistent enough to me to warrant it being
called a bug, regardless of the underlying implementation
details (which I know little of).  I'd expect it work in
both cases, or neither case.

Feel free to close the bug again if you disagree :)

It's quite easy to work around, so I'm not worried greatly
by it.
(workaround:
def f(x):
    class Private:
         pass
    Private.x = x
    return Private
)
msg9856 - (view) Author: Jeremy Hylton (jhylton) (Python triager) Date: 2002-04-22 17:25
Logged In: YES 
user_id=31392

The behavior bugs me too, but I don't expect it will get 
fixed because of the need for backwards compatibility.  The 
local namespace for classes, modules, and functions that 
contain exec or import * are searched using the LOAD_NAME 
opcode.  This opcode implements the old locals, globals, 
builtin search for a name using dict lookup.  If the dict 
lookup fails at any level, the next level up is searched.  
This means an unbound local error will never occur in a 
class block, because the dict lookup just returns NULL and 
the search proceeds to globals.

If anything, the bug is the was "x=x" behaves at the class 
level, but I'm loathe to change it.  It will probably break 
existing code and will require substantial implementation 
effort (I think) because class namespaces aren't 
implemented using the same technique as a function 
namespace.

I'd rather document the existing wart and live with it.  In 
particular, I might document it with the following weasle 
words: "The result of reference an unbound local name in a 
class block is undefined."
msg9857 - (view) Author: Jeremy Hylton (jhylton) (Python triager) Date: 2002-04-22 18:43
Logged In: YES 
user_id=31392

Indeed, after conversation with GvR, we are in agreement 
that it would break too much old code to "fix" this.  Just 
don't write code that abuses the wart at the module level, 
and you'll never feel its a bug when nested inside a 
function <0.1 wink>.
History
Date User Action Args
2022-04-10 16:05:07adminsetgithub: 36300
2002-03-21 01:27:24spivcreate