正如其他人所指出的那樣,叫next(gen)
相當於調用gen.send(None)
。你可以看到這一點,如果你看一下C code for generator objects:
PyDoc_STRVAR(send_doc,
"send(arg) -> send 'arg' into generator,\n\
return next yielded value or raise StopIteration.");
PyObject *
_PyGen_Send(PyGenObject *gen, PyObject *arg)
{
return gen_send_ex(gen, arg, 0);
}
...
static PyObject *
gen_iternext(PyGenObject *gen)
{
return gen_send_ex(gen, NULL, 0);
}
正如你所看到的,iternext
(這是當你調用next(generator_object)
什麼被調用),調用完全相同的方法generator_object.send
,只有它總是通過在NULL
對象。想想看,你的for x in gen
循環基本上是這樣做的相當於:
iterable = iter(gen):
while True:
try:
x = next(iterable)
except StopIteration:
break
print(x)
,您將看到的問題是什麼。
認識到協程和發生器是真正完全獨立的概念是很重要的,儘管它們都是使用yield
關鍵字實現的。一般來說,你不應該迭代一個協程,並且通常你不需要/想將send
的東西放入一個生成器中。我強烈推薦David Beazley的PyCon coroutine tutorial以獲取更多關於此和一般協程的信息。