'Send method using generator. still trying to understand the send method and quirky behaviour
Here is a little function i wrote to understand the send method:
>>> def test():
... for x in xrange(10):
... res = yield
... yield res
>>> a = test()
>>> next(a)
>>> next(a)
>>> next(a)
>>> next(a)
>>> a.send(0)
Traceback (most recent call last):
<ipython-input-220-4abef3782000> in <module>()
StopIteration
>>> a = test()
>>> a.send(0)
Traceback (most recent call last):
<ipython-input-222-4abef3782000> in <module>()
TypeError: can't send non-None value to a just-started generator
>>> a.send(None)
>>> a.send(0)
0
>>> a.send(0)
>>> a.send(0)
0
>>> a.send(0)
>>> a.send(0)
0
>>> a.send(0)
Why is there an Error the first time?
>>> a.send(0)
StopIteration
Why does it require for the first send() to be None? as with this error:
>>> a.send(0)
Traceback (most recent call last):
<ipython-input-222-4abef3782000> in <module>()
TypeError: can't send non-None value to a just-started generator
And then the first send starts the generator( i dont know why) and i send a '0' and it prints it but the second 0 is again none and resumes with whatever i send it(0 here)
>>> a.send(None)
>>> a.send(0)
0
>>> a.send(0)
>>> a.send(0)
0
>>> a.send(0)
>>> a.send(0)
0
This link doesnt help much Python 3: send method of generators
Solution 1:[1]
The send() can only be called if generator is waiting at yield. Since your generator hasn't started executing, calling send() gives you the first error.
Further more, each yield in the generator consumes the value sent by send(). When the second yield statement consumes value but it doesn't use it so that value is discarded. Then you wait on first yield which does consumes value from send() and that value is printed out. So you end up with needing two send().
Here's the fixed version:
>>> def echo():
... while True:
... val = (yield)
... yield val
...
>>> g=echo()
>>> next(g) # move to 1st yield
>>> g.send(2) # execution stops at 2nd yield
2
>>> next(g) # execution stops at 1st yield
>>> g.send(3) # execution stops at 2nd yield
3
Solution 2:[2]
PEP 342 New generator method: send(value) says:
Calling send(None) is exactly equivalent to calling a generator's next() method. Calling send() with any other value is the same, except that the value produced by the generator's current yield expression will be different.
Because generator-iterators begin execution at the top of the generator's function body, there is no yield expression to receive a value when the generator has just been created. Therefore, calling send() with a non-None argument is prohibited when the generator iterator has just started, and a TypeError is raised if this occurs (presumably due to a logic error of some kind). Thus, before you can communicate with a coroutine you must first call next() or send(None) to advance its execution to the first yield expression.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | mon |
