[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