full closures

Luigi Ballabio ballabio at mac.com
Thu Feb 28 11:02:12 CET 2002


At 03:47 PM 2/27/02 -0800, Andrae Muys wrote:
> > I don't understand closures, but I might try something like:
> >
> > class Counter:
> >     def __init__(self):
> >         self.count = 0
> >     def __int__(self):
> >         self.count += 1
> >         return self.count
> >
> > counter = Counter()
> > print "the current count is %d" % counter
> >
>
>That works, as does using a generator:
>
>def Counter():
>     counter = 0
>     while 1:
>         print "the current count is %d % counter
>         counter += 1
>         yield counter - 1   # might as well return it :)

Hi all,
         the usual Scheme closure thing, twisted and perverted to have it 
work in Python but probably very un-Pythonic because of that, would look like:

 >>> def counter(x=0):
...     l = [x-1]
...     def f(l):
...         l[0] += 1
...         return l[0]
...     return lambda: f(l)
...
 >>> c1 = counter()
 >>> c2 = counter(5)
 >>> c1()
0
 >>> c1()
1
 >>> c1()
2
 >>> c2()
5
 >>> c2()
6

Note: the above only works in Python 2.2 (by default) or Python 2.1 (by 
importing nested_scope from __future__)

Much of the awkwardness comes from having to store the counter in a list to 
have pass-by-reference to f, and from having to define a separate f because 
lambda is limited to a single expression. In Scheme, which has different 
semantics, this trick is done much more tersely as

(define (counter x)
   (let ((y (- x 1)))
     (lambda () (set! y (+ y 1)) y)))

which in non-working pseudo-Python syntax for the parens-challenged would be:

def counter(x):
     y = x-1
     return lambda: y += 1; y

but one can't have everything. It wouldn't be Python if it had Scheme 
semantics...

Bye,
         Luigi





More information about the Python-list mailing list