[Python-Dev] closure semantics

Samuele Pedroni pedronis at bluewin.ch
Fri Oct 24 09:53:57 EDT 2003


At 16:22 23.10.2003 -0700, Guido van Rossum wrote:
> > >   def tee(iterable):
> > >       "Return two independent iterators from a single iterable"
> > >       data = {}
> > >       cnt = 0
> > >       def gen(next):
> > >           global* cnt
> > >           dpop = data.pop
> > >           for i in count():
> > >               if i == cnt:
> > >                   item = data[i] = next()
> > >                   cnt += 1
> > >               else:
> > >                   item = dpop(i)
> > >               yield item
> > >       next = iter(iterable).next
> > >       return (gen(next), gen(next))
> > >
> > >which is IMO more readable.
> >
> > it's a subtle piece of code. I wouldn't mind a more structured syntax with
> > both the outer function declaring that is ok for some inner function to
> > rebind some of its locals, and the inner function declaring that a 
> local is
> > coming from an outer scope:
> >
> >    def tee(iterable):
> >        "Return two independent iterators from a single iterable"
> >        data = {}
> >
> >        # cnt = 0 here would be ok
> >
> >       share cnt = 0:  # the assignment is opt,
> >                        # inner functions in the suite can rebind cnt
> >         def gen(next):
> >           use cnt # OR outer cnt
> >          dpop = data.pop
> >            for i in count():
> >                if i == cnt:
> >                    item = data[i] = next()
> >                    cnt += 1
> >                else:
> >                    item = dpop(i)
> >                yield item
> >
> >        # cnt = 0 here would be ok
> >
> >       next = iter(iterable).next
> >        return (gen(next), gen(next))
> >
> > yes it's heavy and unpythonic, but it makes very clear that something
> > special is going on with cnt.
>
>Might as well declare a class then. :-)

well, no, it's probably that I expect rebindable closed-over vars to be 
introduced
but some kind of structured construct instead of the usual Python freeform. 
I think
for this kind of situation I miss the Lisp-y 'let'.

def counter(starval):
    share cnt = startval:
      def inc(i):
        use cnt
        cnt += i
        return cnt
      def dec(i)
        use cnt
        cnt -= i
        return cnt
    return inc,dec

vs.

def counter(starval):
    cnt = startval
    def inc(i):
        global cnt in counter
        cnt += i
        return cnt
    def dec(i)
        global cnt in counter
        cnt -= i
        return cnt
    return inc,dec

vs.

def counter(starval):
    class Counter:
       def __init__(self,startval):
         self.cnt = startval
       def inc(self,i):
         self.cnt += i
         return self.cnt
       def dec(self,i):
         self.cnt += i
         return self.cnt
    newcounter = Counter(startval)
    return newcounter.inc,newcounter.dec

vs.

(defun counter (startval)
               (let ((cnt startval))
                 (flet ((inc (i)
                                 (incf cnt i))
                        (dec (i)
                                 (decf cnt i)))
                   (values #'inc #'dec))))

<wink>




More information about the Python-Dev mailing list