[Tutor] Globals?

Kent Johnson kent37 at tds.net
Sat Nov 13 23:00:53 CET 2004


The issue is whether a closure can rebind a variable in the enclosing 
scope. Python does not allow this except in the special case where the 
enclosing scope is the global scope - then you can use the global 
keyword to rebind it.

But I was responding to the message where you said,
> 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.

Could you explain what behavior you would like to see from this program 
and why it sucks not to get it? My guess is that the problem is that
   x += 1
only rebinds x in the scope of _(), not in the scope of fn(), so the 
change to x is not persistent.

Kent

orbitz wrote:
> Kent, If i follow what you are saying here, I think you are confusing 
> dynamic scope with lexical scope in here.  Dynamic scoping tends to be 
> icky for debugging and usage purposes, and lexical scoping is generally 
> preferred.
> 
> If I'm not following what you are saying here properly please correct me
> 
> 
> Lloyd Kvam wrote:
> 
>> But integers are immutable.
>>
>> If names could be rebound as a side-effect of a function call, you would
>> be creating some difficult to debug connections in your program. 
>> If you are deliberately creating a special environment for communicating
>> between functions sharing that environment (closures), it probably makes
>> sense to use a dictionary or class to separate those variable names from
>> the "general" variables.  A list works, since it is mutable.
>>
>> I guess I'm not a closure purist.
>>
>> On Sat, 2004-11-13 at 15:57, Kent Johnson wrote:
>>  
>>
>>> I think the idea is that x in the enclosing scope should be changed 
>>> when _ is called. To closure purists :-) a language doesn't have 
>>> closures if it can't do this.
>>>
>>> Python will bind the *values* of variables in an enclosing scope into 
>>> a closure, which is good enough for many uses :-)
>>>
>>> Personally I haven't found much need for 'true' closures. orbitz, can 
>>> you say why this is such a pain? How would you use a true closure?
>>>
>>> A workaround is to store the variable in a list, but it's a bit ugly:
>>>
>>> x = [3]
>>> def fn(x):
>>>     def _():
>>>        x[0] += 1
>>>        return x[0]
>>>     return _
>>>
>>> Kent
>>>
>>> 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
>>>>>       
>>>
>>> _______________________________________________
>>> Tutor maillist  -  Tutor at python.org
>>> http://mail.python.org/mailman/listinfo/tutor
>>>   
> 
> 
> 


More information about the Tutor mailing list