当初( PEP 38 )、_yield from
_構文は、「サブジェネレータ」への委任に使用するために導入されました。後でそれは現在 非推奨 ジェネレータベースのコルーチンで使用されました。
一般的にどのような種類のオブジェクト_yield from
_に適用できるかわかりません。私の最初の推測は、イテレータを返すためにオブジェクトの___iter__
_メソッドのみが必要であるというものでした。実際、以下はPython 3.8で機能します。
_class C:
def __init__(self, n):
self.n = n
def __iter__(self):
return iter(range(self.n))
def g(n):
yield from C(n)
print(Tuple(g(3)))
_
ただし、___iter__
_メソッドを持たないasyncio.sleep(1)
などの一部のawaitableでも機能します。
一般的なルールは何ですか?オブジェクトを_yield from
_フォームへの引数として与えることができるかどうかを決定するものは何ですか?
CPython そのステートメントを評価する方法 を確認できます。これからは、コルーチンまたはイテラブルのいずれかである必要があります。
case TARGET(GET_YIELD_FROM_ITER): {
/* before: [obj]; after [getiter(obj)] */
PyObject *iterable = TOP();
PyObject *iter;
if (PyCoro_CheckExact(iterable)) {
/* `iterable` is a coroutine */
if (!(co->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) {
/* and it is used in a 'yield from' expression of a
regular generator. */
Py_DECREF(iterable);
SET_TOP(NULL);
_PyErr_SetString(tstate, PyExc_TypeError,
"cannot 'yield from' a coroutine object "
"in a non-coroutine generator");
goto error;
}
}
else if (!PyGen_CheckExact(iterable)) {
/* `iterable` is not a generator. */
iter = PyObject_GetIter(iterable);
Py_DECREF(iterable);
SET_TOP(iter);
if (iter == NULL)
goto error;
}
PREDICT(LOAD_CONST);
DISPATCH();
}