[Python-ideas] A send() built-in function to drive coroutines
Steven D'Aprano
steve at pearwood.info
Tue Feb 24 12:00:22 CET 2015
On Mon, Feb 23, 2015 at 10:22:05AM -0300, Luciano Ramalho wrote:
> On Mon, Feb 23, 2015 at 10:12 AM, Victor Stinner
> <victor.stinner at gmail.com> wrote:
> > The use case for your send() function is unclear to me. Why not using
> > send() directly?
>
> Bacause the generator may not have started yet, so gen.send() would fail.
>
> > inspect.getgeneratorstate(generator) == 'GEN_CREATED' test looks weird
> > (why do you need it?).
>
> To know that the generator must be primed.
>
> > You should already know if the generator
> > started or not.
>
> I would, if I had written the generator myself. But my code may need
> to work with a generator that was created by some code that I do not
> control.
I must admit I don't understand the problem here. Here's a
simple coroutine:
def runningsum():
total = 0
x = (yield None)
while True:
total += x
x = (yield total)
If I have a function which expects a *primed* coroutine, and you provide
an unprimed one, we get an obvious error:
py> def handle_primed(co):
... for i in (1, 3, 5):
... y = co.send(i)
... return y
...
py> handle_primed(runningsum()) # Oops, unprimed!
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in handle_primed
TypeError: can't send non-None value to a just-started generator
And if I have a function which expects an *unprimed* coroutine, and you
provide a primed one, we will usually get an exception:
py> def handle_unprimed(co):
... next(co)
... for i in (1, 3, 5):
... y = co.send(i)
... return y
...
py> rs = runningsum()
py> next(rs) # Oops, primed!
py> handle_unprimed(rs)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in handle_unprimed
File "<stdin>", line 5, in runningsum
TypeError: unsupported operand type(s) for +=: 'int' and 'NoneType'
I say "usually" because I suppose there are some coroutines which might
accept being sent None and fail to cause an error. But they should be
pretty rare, and in this case I think "consenting adults" should apply:
if I write such a function, I can always inspect the coroutine myself.
So it seems to me that this is a case for documentation, not a built-in
function. Document what you expect, and then it is up to the caller to
provide what you ask for.
Have I missed something? Can you give an example of when you would
legitimately want to accept coroutines regardless of whether they are
primed or not, but don't want to explicitly inspect the coroutine
yourself?
--
Steve
More information about the Python-ideas
mailing list