[Tutor] Globals?

Lloyd Kvam pythonTutor at venix.com
Sun Nov 14 00:05:50 CET 2004


Well, the behavior that you are looking for is quite deliberately not
supported in Python.  I would have described closures as allowing you to
set policy for future execution.  A decision can be made once and then
packaged as a piece of executable code which is used else where.  

I gather that closure purists would expect that code to have the ability
to also rebind variables that lie outside of that executable block.


On Sat, 2004-11-13 at 17:39, orbitz wrote:
> With closures that will work correctly. Since that is the problem they 
> solve (more or less)
> 
> 
> Lloyd Kvam wrote:
> 
> >x = 2
> >def _():
> >    x += 1
> >_()
> >
> >Traceback (most recent call last):
> >  File "/home/lkvam/aa.py", line 6, in -toplevel-
> >    _()
> >  File "/home/lkvam/aa.py", line 4, in _
> >    x += 1
> >UnboundLocalError: local variable 'x' referenced before assignment
> >
> >What is happening is not a closure issue.  Any function that attempts to
> >assign to a non-local variable will get that error.
> >
> >x = 2
> >def _():
> >    global x
> >    x += 1
> >    return x
> >print _()
> >  
> >
> >3
> >
> >This works because we now explicitly reference the variable as a global.
> >
> >I'd hate to think that using global in a closure allows it to change the
> >global x in whatever namespace where it was run, or that the closure
> >would fail if it were run in a namespace that did NOT have a global x. 
> >I'll leave that investigation to others.
> >
> >
> >
> >On Sat, 2004-11-13 at 17:08, orbitz wrote:
> >  
> >
> >>I'm modifying the variable which references it though. Which *should* be 
> >>fine, but Pythons scoping rules and closures are hella messed up.
> >>It should work fine, and it can simplify code. Generally you have to 
> >>make a nested class and return a reference to a method of an instance.
> >>
> >>
> >>Lloyd Kvam wrote:
> >>
> >>    
> >>
> >>>I should have said,
> >>>It is the attempt to change a non-local IMMUTABLE variable.
> >>>
> >>>I still think that is a feature.  If you are trying to change variables
> >>>out side of your local scope, Python requires that they be mutable.
> >>>
> >>>(So I am not a closure purist as Kent pointed out.)
> >>>
> >>>On Sat, 2004-11-13 at 16:56, orbitz wrote:
> >>> 
> >>>
> >>>      
> >>>
> >>>>I know, which is the weakness of python closure's I was pointing out.
> >>>>
> >>>>Lloyd Kvam wrote:
> >>>>
> >>>>   
> >>>>
> >>>>        
> >>>>
> >>>>>It is the attempt to change a non-local variable.
> >>>>>def _():
> >>>>>	return x+1
> >>>>>
> >>>>>will work.
> >>>>>
> >>>>>On Sat, 2004-11-13 at 16:28, orbitz wrote:
> >>>>>
> >>>>>
> >>>>>     
> >>>>>
> >>>>>          
> >>>>>
> >>>>>>Hrm, it does not work like there here:
> >>>>>>
> >>>>>>Python 2.3.3 (#2, Mar 19 2004, 19:14:13)
> >>>>>>[GCC 3.2.1 [FreeBSD] 20021119 (release)] on freebsd5
> >>>>>>Type "help", "copyright", "credits" or "license" for more information.
> >>>>>>       
> >>>>>>
> >>>>>>            
> >>>>>>
> >>>>>>>>>def fn(x):
> >>>>>>>>>             
> >>>>>>>>>
> >>>>>>>>>                  
> >>>>>>>>>
> >>>>>>...     def _():
> >>>>>>...             x += 1
> >>>>>>...             return x
> >>>>>>...     return _
> >>>>>>...
> >>>>>>       
> >>>>>>
> >>>>>>            
> >>>>>>
> >>>>>>>>>blah = fn(2)
> >>>>>>>>>blah()
> >>>>>>>>>             
> >>>>>>>>>
> >>>>>>>>>                  
> >>>>>>>>>
> >>>>>>Traceback (most recent call last):
> >>>>>>File "<stdin>", line 1, in ?
> >>>>>>File "<stdin>", line 3, in _
> >>>>>>UnboundLocalError: local variable 'x' referenced before assignment
> >>>>>>
> >>>>>>And doing def _(x = x) does not fix the trick either.
> >>>>>>
> >>>>>>       
> >>>>>>
> >>>>>>            
> >>>>>>
> >>>>>>>>>blah = fn(2)
> >>>>>>>>>blah()
> >>>>>>>>>             
> >>>>>>>>>
> >>>>>>>>>                  
> >>>>>>>>>
> >>>>>>3
> >>>>>>       
> >>>>>>
> >>>>>>            
> >>>>>>
> >>>>>>>>>blah()
> >>>>>>>>>             
> >>>>>>>>>
> >>>>>>>>>                  
> >>>>>>>>>
> >>>>>>3
> >>>>>>       
> >>>>>>
> >>>>>>            
> >>>>>>
> >>>>>>>>>blah()
> >>>>>>>>>             
> >>>>>>>>>
> >>>>>>>>>                  
> >>>>>>>>>
> >>>>>>3
> >>>>>>
> >>>>>>Do real closures exist in 2.4?
> >>>>>>
> >>>>>>Lloyd Kvam wrote:
> >>>>>>
> >>>>>>  
> >>>>>>
> >>>>>>       
> >>>>>>
> >>>>>>            
> >>>>>>
> >>>>>>>It DOES work in current versions of Python, exactly as you coded it.
> >>>>>>>
> >>>>>>>In older Pythons (e.g. 1.52) you would have had to specifying the
> >>>>>>>enclosing variables explicitly
> >>>>>>>	def _(x=x):
> >>>>>>>
> >>>>>>>A lot of old critiques are still present on the web.  wikipedia has a
> >>>>>>>terrific article describing Python that is current (at least 2.3.3).
> >>>>>>>
> >>>>>>>http://en.wikipedia.org/wiki/Python_programming_language
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>On Sat, 2004-11-13 at 14:07, orbitz wrote:
> >>>>>>>
> >>>>>>>
> >>>>>>>    
> >>>>>>>
> >>>>>>>         
> >>>>>>>
> >>>>>>>              
> >>>>>>>
> >>>>>>>>In my opinion, this behavior really sucks too. Like when it comes to 
> >>>>>>>>closures.  As far as I know, Python does not *really* support closures, 
> >>>>>>>>like you would get with something like lisp. Correct me if I'm wrong.  
> >>>>>>>>This means code like:
> >>>>>>>>
> >>>>>>>>def fn(x):
> >>>>>>>> def _():
> >>>>>>>>    x += 1
> >>>>>>>>    return x
> >>>>>>>> return _
> >>>>>>>>
> >>>>>>>>Will not work, which can be a pain in the ass.
> >>>>>>>>
> >>>>>>>>
> >>>>>>>>Kent Johnson wrote:
> >>>>>>>>
> >>>>>>>> 
> >>>>>>>>
> >>>>>>>>      
> >>>>>>>>
> >>>>>>>>           
> >>>>>>>>
> >>>>>>>>                
> >>>>>>>>
> >>>>>>>>>Liam,
> >>>>>>>>>
> >>>>>>>>>When you make any assignment to a variable inside a function, Python 
> >>>>>>>>>assumes that the variable is local to the function. Then any use of 
> >>>>>>>>>the variable before it's first assignment is an error.
> >>>>>>>>>
> >>>>>>>>>To force a variable in a function to be global, put a 'global' 
> >>>>>>>>>statement in the function. You need to add
> >>>>>>>>>global badConnectCycle
> >>>>>>>>>to your function getReturns
> >>>>>>>>>
> >>>>>>>>>If you don't make any assignment to a variable, then the global 
> >>>>>>>>>(module) namespace is searched. That is why badUserList works fine - 
> >>>>>>>>>you never assign it, you just access the list methods.
> >>>>>>>>>
> >>>>>>>>>Kent
> >>>>>>>>>
> >>>>>>>>>Liam Clarke wrote:
> >>>>>>>>>
> >>>>>>>>>   
> >>>>>>>>>
> >>>>>>>>>        
> >>>>>>>>>
> >>>>>>>>>             
> >>>>>>>>>
> >>>>>>>>>                  
> >>>>>>>>>
> >>>>>>>>>>Hi all,
> >>>>>>>>>>Having trouble with something, it is 3:30am in the morning, so this
> >>>>>>>>>>may be a dumb problem, if so, I apologise.
> >>>>>>>>>>
> >>>>>>>>>>In my prog, there's two variables created right at the get go -
> >>>>>>>>>>
> >>>>>>>>>>import imaplib
> >>>>>>>>>>import email.Parser
> >>>>>>>>>>import os
> >>>>>>>>>>import os.path
> >>>>>>>>>>import datetime
> >>>>>>>>>>import md5
> >>>>>>>>>>          
> >>>>>>>>>>
> >>>>>>>>>>               
> >>>>>>>>>>
> >>>>>>>>>>                    
> >>>>>>>>>>
> >>>>>>>>>>from pause import *
> >>>>>>>>>        
> >>>>>>>>>
> >>>>>>>>>             
> >>>>>>>>>
> >>>>>>>>>                  
> >>>>>>>>>
> >>>>>>>>>>badUserList=[]
> >>>>>>>>>>badConnectCycle=0
> >>>>>>>>>>
> >>>>>>>>>>as I want them to be global within this module, so that another module
> >>>>>>>>>>can pick them out easily.
> >>>>>>>>>>
> >>>>>>>>>>Now, I just added badConnectCycle, badUserList has been there awhile,
> >>>>>>>>>>and it's used in
> >>>>>>>>>>
> >>>>>>>>>>the function connectToImap which is called by getReturns which is
> >>>>>>>>>>called by main(), and my other module can get it no problem, so
> >>>>>>>>>>badUserList is fine.
> >>>>>>>>>>
> >>>>>>>>>>badConnectCycle... is giving me errors -
> >>>>>>>>>>
> >>>>>>>>>>badConnectCycle is used in getReturns, as so -
> >>>>>>>>>>if session == "NoConnect" :             badConnectCycle += 1
> >>>>>>>>>>         continue
> >>>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>>function getReturns ends as follows -
> >>>>>>>>>>if badConnectCycle == len(user) and badConnectCycle > 0: return 
> >>>>>>>>>>("NoConnect","")
> >>>>>>>>>>if badUserList and not sender: return ('NoLogin',"")
> >>>>>>>>>>if matchindex[0] and not sender: return ('NoNew', '')
> >>>>>>>>>>if not sender: return ("NoMatch","")
> >>>>>>>>>>return (sender, msgdata)
> >>>>>>>>>>
> >>>>>>>>>>and it's at that line
> >>>>>>>>>>
> >>>>>>>>>>if badConnectCycle == len(user) and badConnectCycle > 0:
> >>>>>>>>>>
> >>>>>>>>>>that I get this error:
> >>>>>>>>>>
> >>>>>>>>>>UnboundLocalError: local variable 'badConnectCycle' referenced before
> >>>>>>>>>>assignment.
> >>>>>>>>>>
> >>>>>>>>>>Which is confusing me because badUserList is used within a function
> >>>>>>>>>>called by getReturns, and I've had no problem with it.
> >>>>>>>>>>
> >>>>>>>>>>Help anyone? Much appreciated if you can.
> >>>>>>>>>>
> >>>>>>>>>>Regards,
> >>>>>>>>>>
> >>>>>>>>>>Liam Clarke
> >>>>>>>>>>     
> >>>>>>>>>>
> >>>>>>>>>>          
> >>>>>>>>>>
> >>>>>>>>>>               
> >>>>>>>>>>
> >>>>>>>>>>                    
> >>>>>>>>>>
> >>>>>>>>>_______________________________________________
> >>>>>>>>>Tutor maillist  -  Tutor at python.org
> >>>>>>>>>http://mail.python.org/mailman/listinfo/tutor
> >>>>>>>>>
> >>>>>>>>>   
> >>>>>>>>>
> >>>>>>>>>        
> >>>>>>>>>
> >>>>>>>>>             
> >>>>>>>>>
> >>>>>>>>>                  
> >>>>>>>>>
> >>>>>>>>_______________________________________________
> >>>>>>>>Tutor maillist  -  Tutor at python.org
> >>>>>>>>http://mail.python.org/mailman/listinfo/tutor
> >>>>>>>> 
> >>>>>>>>
> >>>>>>>>      
> >>>>>>>>
> >>>>>>>>           
> >>>>>>>>
> >>>>>>>>                
> >>>>>>>>
-- 
Lloyd Kvam
Venix Corp



More information about the Tutor mailing list