[Tutor] scoping rules

dman dsh8290@rit.edu
Sun, 6 Jan 2002 16:14:51 -0500


First: Karthik, can you please ask new questions by creating a new
mail message instead of replying to an existing one?  I tend to lose
your questions in the middle of other threads.

On Sun, Jan 06, 2002 at 02:30:09PM +0530, Karthik Gurumurthy wrote:
| 
| Just wanted to confirm the scoping rules.
| 
| >>> a = 1298
| >>> def func(x):
| 	a = 908
| 	def func(x):
| 		print "isnide func"
| 		print "\tlocals",locals()
| 		print "\tglobals",globals()
| 		i =123
| 		print "\tlocals again",locals()
| 		a+=1 		###statement
| 		print a
| 	print "ok",locals()
| 	func(87)
| 	print a
| 
| i observed the following.
| 
| When i commented the marked statement inside the inner func,
| a (908 from the enclosing function's local namespace) was present in the
| inner function's local namespace.
| the global a was present in the global namespace.fine.
| 
| The moment i uncomment it (ie a = a + 1), the reference to "enclosing
| function's a" from locals() of
| inner func was removed.
| 
| BUT, reference to a in the global namespace remained. Then why did'nt it
| increment the global a?
| since it is supposed to look up the locals() first and when not found search
| globals()?
| instead i got an unbound error.
| 
| Does it mean that moment we try to add to / manipulate a variable, python
| expects the variable to
| be initialized in the function's own local namespace? I mean as long as we
| are "reading", it is all fine.
| 
| it worked when i put the flag global a right in the begining of the
| function.
| 
| Does this mean that i will not be able to increment a (908) (defined in the
| enclosing function)
| inside the inner function?

You are right.  Here's what's going on :

When you have an assignment statement, a new local variable is
created.  The compiler (with the nested scopes modifications) will
flag those names as being local.  When you have the "a+=1" line the
compiler sees that 'a' is a local variable.  Thus you get the
"UnboundLocal" error when you try and reference 'a' (to get it's
original value).  If you say 'global' it works only because 'a' is at
the module level.  If you say 'global a' and then assign to 'a', 'a'
is going to be at the module level.  For example this won't work :

def f() :
    a = 908
    def g() :
        global a
        a+=1
    g()
f()


The limitation with nested scopes is that you can't assign to any
variable that is not local or global (module-level).  The problem is:
how will the compiler know which scope you want to assign in?  In
C/C++/Java it is known based on variable declarations, but python
doesn't have that.

HTH,
-D

-- 

"GUIs normally make it simple to accomplish simple actions and
impossible to accomplish complex actions."
    --Doug Gwyn  (22/Jun/91 in comp.unix.wizards)