msg84257 - (view) |
Author: (qwjqwj) |
Date: 2009-03-27 12:25 |
In Python 3.0,3.1a1:
>>> def f():
[(yield i) for i in range(10)]
>>> f()
>>> f() is None
True
>>> def f():
((yield i) for i in range(10))
>>> f()
>>> f() is None
True
However it is correct in Python 2.5,2.6
>>> def f():
... [(yield i) for i in range(10)]
...
>>> f()
<generator object f at 0x2b84bbe3ae60>
|
msg84267 - (view) |
Author: Antoine Pitrou (pitrou) * |
Date: 2009-03-27 15:48 |
Perhaps you forgot to return the value. In 3.1:
>>> def f():
... return [(yield i) for i in range(10)]
...
>>> f()
<generator object <listcomp> at 0x7f9bcc2257d0>
|
msg84268 - (view) |
Author: Antoine Pitrou (pitrou) * |
Date: 2009-03-27 15:53 |
It's true, however, that there is a difference in behaviour between 2.x
and 3.x here.
In 2.x, the function containing the list comprehension is a generator.
In 3.x, it's the list comprehension itself which becomes a generator.
I'm not sure which one is more useful. Also, it's likely that this won't
be changed, because it's due to the compilation model of list
comprehensions (which are compiled as a separate code object in 3.x).
|
msg84270 - (view) |
Author: (qwjqwj) |
Date: 2009-03-27 16:12 |
Why should yield can be put inside the iterator? The behavior here is
very weired.
>>> x = [(yield i) for i in range(10)]
>>> print(list(x))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, [None, None, None, None, None, None,
None, None, None, None]]
|
msg84271 - (view) |
Author: (qwjqwj) |
Date: 2009-03-27 16:13 |
>>> x = ((yield i) for i in range(10))
>>> list(x)
[0, None, 1, None, 2, None, 3, None, 4, None, 5, None, 6, None, 7, None,
8, None, 9, None]
|
msg84272 - (view) |
Author: (qwjqwj) |
Date: 2009-03-27 16:14 |
>>> x = {(yield i) for i in range(10)}
>>> x
<generator object <setcomp> at 0x02A453F0>
>>> list(x)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, {None}]
|
msg84273 - (view) |
Author: (qwjqwj) |
Date: 2009-03-27 16:33 |
More experiments:
The tuple pair (10,20) don't correspond to (i,i*i)
The yield order is distorted
>>> x = (((yield i),(yield i*i)) for i in range(3))
>>> x.__next__()
0
>>> x.send(10)
0
>>> x.send(20)
(10, 20)
>>> x.send(30)
1
>>> x.send(40)
1
>>> x.send(60)
(40, 60)
>>> x.send(70)
2
>>> x.send(80)
4
>>> x.send(90)
(80, 90)
>>> x.send(100)
Traceback (most recent call last):
File "<pyshell#107>", line 1, in <module>
x.send(100)
StopIteration
|
msg84274 - (view) |
Author: Antoine Pitrou (pitrou) * |
Date: 2009-03-27 16:41 |
> More experiments:
> The tuple pair (10,20) don't correspond to (i,i*i)
This is normal, since it corresponds to ((yield i), (yield i*i)).
The value of a yield expression is what the caller puts into send(), not
what is yielded to the caller. And since you sent 10 then 20, the
resulting tuple is (10, 20).
> The yield order is distorted
It is quite logical actually. The generator first has to yield two
values before being able to produce a third one (the tuple consisting of
the value of two "yield" expressions).
|
msg84275 - (view) |
Author: (qwjqwj) |
Date: 2009-03-27 16:52 |
Ok, I see. Thanks.
However, I don't think yield should be consumed at the iterator's level.
It may be more useful for the outside function to consume the yield.
For example, some function want to change some data with another "thread".
def f():
...fetch data...
x = [yield i for i in data]
It should be written as belowed in Python 3.1 now
def f():
x = []
for i in data:
x.append((yield i))
|
msg84278 - (view) |
Author: Guido van Rossum (gvanrossum) * |
Date: 2009-03-27 18:58 |
Can anyone think of a *reason* to put a yield inside a generator
expression? ISTM we could just forbid this syntactically. It seems
insane and hard to read so if someone has a reason they should write it
out using an explicit for-statement.
|
msg84288 - (view) |
Author: Terry J. Reedy (terry.reedy) * |
Date: 2009-03-27 23:29 |
I think this should just be closed.
The original implied claim that 3.0 is not correct is not correct. The
change of behavior is a clear side effect of and intended and documented
change in the semantics of comprehensions.
As near as I can tell, the results of the experiments are all correct
according to the doc for yield.
Python-list or the python-ideas list is more appropriate than the
tracker to discuss a semantic change. In any case, comprehensions are
function expressions, like lambda expressions, and expressions therein
should act much the same as the expression in a lambda expression.
Even if unclear, slightly insane, and not very useful, I do not think
yield should be prohibited in generators expression because
1) it would introduce a back-incompatibility in 3.1;
2) it would slightly break the parallelism with other comprehensions;
3) it would slightly break the parallelism with the expanded for-form;
4) such use is unlikely in real practice; and
5) it would raise the question of where else to prohibit yield.
|
msg84289 - (view) |
Author: Guido van Rossum (gvanrossum) * |
Date: 2009-03-27 23:30 |
Fine!
|
|
Date |
User |
Action |
Args |
2022-04-11 14:56:47 | admin | set | github: 49827 |
2009-03-27 23:30:50 | gvanrossum | set | status: open -> closed resolution: wont fix messages:
+ msg84289
|
2009-03-27 23:29:10 | terry.reedy | set | nosy:
+ terry.reedy messages:
+ msg84288
|
2009-03-27 18:58:28 | gvanrossum | set | nosy:
+ gvanrossum messages:
+ msg84278
|
2009-03-27 16:52:21 | qwjqwj | set | messages:
+ msg84275 |
2009-03-27 16:41:37 | pitrou | set | messages:
+ msg84274 |
2009-03-27 16:33:26 | qwjqwj | set | messages:
+ msg84273 |
2009-03-27 16:14:44 | qwjqwj | set | messages:
+ msg84272 |
2009-03-27 16:13:02 | qwjqwj | set | messages:
+ msg84271 |
2009-03-27 16:12:11 | qwjqwj | set | messages:
+ msg84270 |
2009-03-27 15:53:33 | pitrou | set | messages:
+ msg84268 |
2009-03-27 15:48:52 | pitrou | set | nosy:
+ pitrou messages:
+ msg84267
|
2009-03-27 12:25:13 | qwjqwj | create | |