What are python closures realy like?

Paddy paddy3118 at netscape.net
Wed Dec 6 01:59:29 EST 2006


Karl Kofnarson wrote:

> > Karl,
> >
> > Usually when using this idiom, fun_basket would return a tuple of all of the
> > defined functions, rather than one vs. the other.  So in place of:
> >>    if f == 1:
> >>        return f1
> >>    if f == 2:
> >>        return f2
> > Just do
> >>    return f1, f2
> > (For that matter, the argument f is no longer needed either.)
> >
> > Then your caller will get 2 functions, who share a common var.  You don't
> > call fun_basket any more, you've already created your two "closures".  Call
> > fun_basket using something like:
> >
> > z1,z2 = fun_basket(None)
> >
> > And then call z1() and z2() at your leisure - they should have the desired
> > behavior.
> >
> > -- Paul
>
> Thanks a lot Paul and for the other answers. The things are now
> clear to me. In fact, in the Lisp example that I mentioned, you
> get a list (or let it be association list) of the internal
> functions. Then you can call them separately and they work as
> you expect but it's due to the fact only that you got them created
> at the same time.

I played around a bit. The following is a 'borg'  version in that there
is only one counter shared between all calls of the outer function:

>>> def fun_borg_var(initial_val=0):
... 	def borg_var_inc(x=1):
... 		fun_borg_var._n += x
... 		return fun_borg_var._n
... 	def borg_var_dec(x=1):
... 		fun_borg_var._n -= x
... 		return fun_borg_var._n
... 	try:
... 		fun_borg_var._n = fun_borg_var._n
... 	except:
... 		fun_borg_var._n = initial_val
... 	return (borg_var_inc, borg_var_dec)
...
>>> up1, dn1 = fun_borg_var()    # get an inc/decrementer
>>> up1(0)
0
>>> up1()
1
>>> up1()
2
>>> dn1()
1
>>> dn1()
0
>>> dn1()
-1
>>> up2, dn2 = fun_borg_var()    # get another inc/decrementer
>>> up2(0)                       # looks like the same _n
-1
>>> up2(3) 
2
>>> up1(3)
5
>>> 


- Paddy.




More information about the Python-list mailing list