[Python-Dev] accumulator display syntax

Guido van Rossum guido at python.org
Tue Oct 21 22:23:07 EDT 2003


Urgh, we need this sorted out before Raymond can rewrite PEP 289 and
present it to c.l.py...

> [Samuele Pedroni]
> > so this, if I understand:
> >
> > def h():
> >    y = 0
> >    l = [1,2]
> >    it = (x+y for x in l)
> >    y = 1
> >    for v in it:
> >      print v
> >
> > will print 1,2 and not 2,3
> 
> That is what I had in mind, and that if the first assignment to "y" were
> commented out, the assignment to "it" would raise UnboundLocalError.
> 
> > unlike:
> >
> > def h():
> >    y = 0
> >    l = [1,2]
> >    def gen(S):
> >      for x in S:
> >        yield x+y
> >    it = gen(l)
> >    y = 1
> >    for v in it:
> >      print v
> 
> Yes, but like it if you replaced the "def gen" and the line following it
> with:
> 
>     def gen(y=y, l=l):
>         for x in l:
>             yield x+y
>     it = gen()
> 
> This is worth some thought.  My intuition is that we *don't* want "a
> closure" here.  If generator expressions were reiterable, then (probably
> obnoxiously) clever code could make some of use of tricking them into using
> different inherited bindings on different (re)iterations.  But they're
> one-shot things, and divorcing the values actually used from the values in
> force at the definition site sounds like nothing but trouble to me
> (error-prone and surprising).  They look like expressions, after all, and
> after
> 
>     x = 5
>     y = x**2
>     x = 10
>     print y
> 
> it would be very surprising to see 100 get printed.  In the rare cases
> that's desirable, creating an explicit closure is clear(er):
> 
>     x = 5
>     y = lambda: x**2
>     x = 10
>     print y()
> 
> I expect creating a closure instead would bite hard especially when building
> a list of generator expressions (one of the cases where delaying generation
> of the results is easily plausible) in a loop.  The loop index variable will
> probably play some role (directly or indirectly) in the intended operation
> of each generator expression constructed, and then you severely want *not*
> for each generator expression to see "the last" value of the index vrlbl.

Right.

> For concreteness, test_generators.Queens.__init__ creates a list of rowgen()
> generators, and rowgen uses the default-arg trick to give each generator a
> different value for rowuses; it would be an algorithmic disaster if they all
> used the same value.
> 
> Generator expressions are too limited to do what rowgen() does (it needs to
> create and undo side effects as backtracking proceeds), so it's not
> perfectly relevant as-is.  I *suspect* that if people work at writing
> concrete use cases, though, a similar thing will hold.
> 
> BTW, Icon can give no guidance here:  in that language, the generation of a
> generator's result sequence is inextricably bound to the lexical occurrence
> of the generator.  The question arises in Python because definition site and
> generation can be divorced.

So, do you want *all* free variables to be passed using the
default-argument trick (even globals and builtins), or only those that
correspond to variables in the immediately outer scope, or only those
corresponding to function scopes (as opposed to globals)?

n = 0
def f():
    global n
    n += 1
    return n
print list(n+f() for x in range(10))

--Guido van Rossum (home page: http://www.python.org/~guido/)



More information about the Python-Dev mailing list