[Tutor] Why thus?

Wesley J. Chun wesc@alpha.ece.ucsb.edu
Sun, 12 Mar 2000 13:51:44 -0800 (PST)


    > Date: Sun, 12 Mar 2000 22:29:57 +0100
    > From: Christian Tismer <tismer@tismer.com>
    > 
    > The difference is: When compiling your code, the compiler
    > tries to figure out what is global and what not. Since
    > counter is assigned to, it becomes a local. But the object
    > does not yet exist when you request it:
    >    counter=counter+1
    > wants to retrieve the current value, and it isn't set yet.
    > You are accessing a local variable which already has its
    > slot and is ready to receive a value, but cannot until
    > it is initialized.


chris is absolutely right.  when doing an assignment in a
local scope, the compiler will search only for the local
name, and since you haven't done a "counter = XXX" within
__init__(), it will complain.

here is an easier example of the exact same problem outside
the class realm (since it really doesn't have anything to
do with classes):

# this works  (no assignment)
i = 4
def foo():
    print i   # print global 'i'


# this fails (references local var that hasn't been
#		assigned/doesn't exist)
i = 4
def foo():
    print i   # "print global 'i'"
    i = 6     # set local 'i'

the result is a "NameError: i".  upon seeing the presence
of a local 'i' makes any previous code *think* it should
access a local 'i' vs. the global one.

i asked Guido to confirm this or to check if it was his
way to punish the programmer for writing such horrid code?      ;-)
here was his reply:

    The compiler does an analysis of the whole func-
    tion body and decides that i is a local variable.
    Then all references to i are made into local vari-
    able references.  Local refs are much faster than
    global variable references: locals are indexed in
    an array, globals are a dict lookup.  So the
    ``print i'' accesses the local variable i but it
    isn't defined yet.  In Python 1.6, this will
    raise UnboundLocalError (a subclass of NameError):

    >>> def f(): print i; i = 1
    >>> f()
    Traceback (innermost last):
      File "<stdin>", line 1, in ?
      File "<stdin>", line 1, in f
    UnboundLocalError: i


hope this helps!!

-wesley

"Core Python Programming", Prentice-Hall, TBP Summer 2000
(will have an example like this in here too!)

wesley.j.chun :: wesc@alpha.ece.ucsb.edu
cyberweb.consulting :: silicon.valley, ca
http://www.roadkill.com/~wesc/cyberweb/