On 9/8/2010 2:18 PM Russell Warren said...
I'm having trouble understanding when variables are added to
namespaces.  I thought I understood it, but my nested function
examples below have me very confused.

Take a look at PEP 227 where nested scopes are introduced.

http://www.python.org/dev/peps/pep-0227/

From the PEP:

    If a name is used within a code block, but it is not bound there
    and is not declared global, the use is treated as a reference to
    the nearest enclosing function region.


In each test function below I have an x variable (so "x" is in the
namespace of each test function).  I also have a nested function in
each (innerFunc) that has different flavors of trying to access or
assign a variable named "x".

---
def test1():
     print "running test1..."
     x = 1
     def innerFunc():
         print "inner locals():",
         print "%s" % locals()  # x not present (yet)
         x = 2
         print x
     innerFunc()
     print "x left as %s\n" % x

def test2():
     print "running test2..."
     x = 1
     def innerFunc():
         print "inner locals():",
         print "%s" % locals()  # x not present
     innerFunc()
     print "x left as %s\n" % x

def test3():
     print "running test3..."
     x = 1
     def innerFunc():
         print "inner locals():",
         print "%s" % locals()  # how is x in locals in this case??
         print x
     innerFunc()
     print "x left as %s\n" % x

test1()
test2()
test3()

---

With the nested scope rules, I thought that *at the time of* trying to
access an object with a given name, if the name was not available in
the namespace of the local function python would then check the
namespace of the parent function.  My tests above don't seem to match
this.  Specifically my "at the time of" assumption.

What is happening in test3?  How is it that "x" ends up in the local
namespace before it is ever referenced?  It seems that, prior to
execution time, the python compiler is "magically" determining that
I'm referencing a particular name before assignment and shoving it
into the local namespace so it can be used.  I did not think the
compiler went into function bodies, aside from basic syntax checking.

Further confusing me (or confirming the compiler behavior) is adding a
4th test with only one added line...

def test4():
     print "running test4..."
     x = 1
     def innerFunc():
         print "inner locals():",
         print "%s" % locals()  # how is x in locals in this case??
         print x
         x = 2  #ONLY ADDED LINE TO TEST3
     innerFunc()
     print "x left as %s\n" % x

In this case I get "UnboundLocalError: local variable 'x' referenced
before assignment".  I think this means that the compiler (prior to
runtime) inspected the code, determined I will do an assignment,

x is local by virtue of being assigned to within the function.

decided _not_ to bring the parent's x into the local namespace, and as
a result caused the unbound name problem at runtime.

It seems that the parent's "x" is brought directly into the local
namespace (when appropriate), rather than the namespace lookup just
moving up the hierarchy when not found.  This is confusing to me and
is making me question my understanding of namespace lookups.  Are
nested scopes a special case where the lookup is handled differently?

What if I want to change the value of the parent's "x"?  test4 implies
that I can't.

You can't ever unless x is mutable.


Have I got this right?  Can someone please clarify what is going on?



I don't have time to go into further details at the moment.

HTH,

Emile


--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to