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: weird namespace phenomenon
Type: Stage:
Components: Interpreter Core Versions:
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: tim.peters Nosy List: tim.peters
Priority: normal Keywords:

Created on 2001-09-21 18:26 by anonymous, last changed 2022-04-10 16:04 by admin. This issue is now closed.

Messages (2)
msg6636 - (view) Author: Nobody/Anonymous (nobody) Date: 2001-09-21 18:26
# == module f.py
y = 10

def g():

  if y:
    y = 100

  return y

# == module h.py

import f
print f.g()

# == plop these two modules into the same directory
and 'cd' to that directory.

When you run 'python h.py' at the command line, line 6 
of f.py (if y:)
creates a problem due to f being supposedly undefined. 
The error is
registered as NameError or UnboundLocalError depending 
on what version 
of the python core you're running.   Python 2.1.x says 
y is being 
referenced before assignment, yet if you change the 
_next_ line to read
"z = 100" rather than "y = 100", the whole thing runs 
fine, printing 10
(the value of f.y) at the end as expected.

This is at the very least an extreme logic quirk in 
how python namespaces
work, and at worst a bug badly in need of correction 
(since vsn 1.5.2 or
before).
msg6637 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2001-09-21 20:15
Logged In: YES 
user_id=31435

Whether a given name is local or global in a given scope is 
a property determined at compile-time, not at runtime.  See 
the Reference Manual for details.  In brief, if a name is 
bound ("assigned to") *anywhere* in the body of a function, 
that name is local throughout the entire function.  You 
assign to y in the body of g(), therefore y is a local 
variable everywhere in g(), and you reference y's value in g
() before giving it a value (hence it's an unbound local at 
the time you first reference it, hence UnboundLocalError in 
recent Pythons).  The y in the body of g() has nothing to 
do with the module-level vrbl y.  If you intended to 
reference the module-level vrbl y, then you need to put

global y

as the first statement in g().

But it's impossible for me to guess what you intended -- 
and it's also impossible for Python.

If you're familiar with C, it's exactly the same as

int y = 10;

int g() {int y; if (y) y = 100; return y;}

except that in C you'd get random crap out of that function 
(due to referencing an uninitialized auto) instead of a 
reliable exception.  The difference is that Python doesn't 
have explict declarations for local variables, but the fact 
that you assigned to y within the body of g makes y a local 
just as much as y is function-local in the C example above.
History
Date User Action Args
2022-04-10 16:04:27adminsetgithub: 35220
2001-09-21 18:26:45anonymouscreate