Skip to content

NameError assigning to class in a func #36300

Description

@spiv
mannequin
BPO 532860

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = <Date 2002-04-22.18:43:12.000>
created_at = <Date 2002-03-21.01:27:24.000>
labels = ['interpreter-core']
title = 'NameError assigning to class in a func'
updated_at = <Date 2002-04-22.18:43:12.000>
user = 'https://bugs.python.org/spiv'

bugs.python.org fields:

activity = <Date 2002-04-22.18:43:12.000>
actor = 'jhylton'
assignee = 'jhylton'
closed = True
closed_date = None
closer = None
components = ['Interpreter Core']
creation = <Date 2002-03-21.01:27:24.000>
creator = 'spiv'
dependencies = []
files = []
hgrepos = []
issue_num = 532860
keywords = []
message_count = 5.0
messages = ['9853', '9854', '9855', '9856', '9857']
nosy_count = 2.0
nosy_names = ['jhylton', 'spiv']
pr_nums = []
priority = 'normal'
resolution = 'wont fix'
stage = None
status = 'closed'
superseder = None
type = None
url = 'https://bugs.python.org/issue532860'
versions = ['Python 2.2']

Activity

  1. spiv commented on Mar 21, 2002

    spivmannequin
    MannequinAuthor

    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)

  2. jhylton commented on Apr 19, 2002

    jhyltonmannequin
    Mannequin

    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?

  3. spiv commented on Apr 22, 2002

    spivmannequin
    MannequinAuthor

    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
    )

  4. jhylton commented on Apr 22, 2002

    jhyltonmannequin
    Mannequin

    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."

  5. jhylton commented on Apr 22, 2002

    jhyltonmannequin
    Mannequin

    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>.

  6. transferred this issue fromon Apr 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions