Confused about nested scopes and when names get added to namespaces
Emile van Sebille
emile at fenx.com
Wed Sep 8 18:47:38 EDT 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