[Tutor] Globals?

Lloyd Kvam pythonTutor at venix.com
Sat Nov 13 23:33:39 CET 2004


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