[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