En Sat, 21 Apr 2007 06:21:00 -0300, Boris Borcic <bb*****@gmail.com>
escribió:
>>x = (lambda : ((yield 666),(yield 777),(yield 888)))()
>>x.next()
666
>>x.next()
777
>>x.next()
888
>>x.next()
(None, None, None)
I think nobody thought in advance this case (a lambda expression with
yield?), else it would have been forbidden. The lambda is roughly
equivalent to:
def anonymous():
return ((yield 666),(yield 777),(yield 888))
x = anonymous()
but *that* function is forbidden: a generator cannot contain a "return
something" statement. Writing it as a lambda expression, you are bypassing
the compiler check.
Those three None are the 3 yield values, combined into one tuple. You can
verify using send instead of next; the Nones are replaced by the received
values:
pyx = (lambda : ((yield 666),(yield 777),(yield 888)))()
pyx.send(None)
666
pyx.send(1)
777
pyx.send(2)
888
pyx.send(3)
(1, 2, 3)
That was the return in effect. As the function (or lambda) is exited, the
next try should raise StopIteration:
pyx.send(4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Let's check with dis:
pydis.dis(x.gi_frame.f_code)
1 0 LOAD_CONST 0 (666)
3 YIELD_VALUE
4 LOAD_CONST 1 (777)
7 YIELD_VALUE
8 LOAD_CONST 2 (888)
11 YIELD_VALUE
12 BUILD_TUPLE 3
15 RETURN_VALUE
>>x = (lambda : ((yield 666),(yield 777),(yield 888)) and None)()
>>x.next()
666
>>x.next()
777
>>x.next()
888
>>x.next()
Traceback (most recent call last):
File "<pyshell#29>", line 1, in <module>
x.next()
StopIteration
>>>
This time, the ((tuple) and None) is like saying "discard the tuple and
return None instead", and that fires the usual StopIteration.
--
Gabriel Genellina