Confused about nested scopes and when names get added to namespaces

Emile van Sebille emile at fenx.com
Thu Sep 9 00:47:38 CEST 2010


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





More information about the Python-list mailing list