Вы неправильно прочитали PEP8. PEP8 заявляет:
Будьте последовательны в ответных заявлениях. Либо все операторы возврата в функции должны возвращать выражение, либо ни один из них не должен.
(жирный акцент мой)
Вы должны соответствовать тому, как вы используете return
в одной функции, а не во всем проекте.
Используйте return
, это единственный оператор return
в функции.
Однако я не вижу ни одного варианта использования, в котором мог бы произойти возврат значения из функции генератора.
Возвращаемое значение генератора присоединяется к возбужденному исключению StopIteration
:
>>> def gen():
... if False: yield
... return 'Return value'
...
>>> try:
... next(gen())
... except StopIteration as ex:
... print(ex.value)
...
Return value
И это также механизм, с помощью которого yield from
производит значение; возвращаемое значение yield from
является атрибутом value
в исключении StopIteration
. Таким образом, генератор может вернуть результат в код, используя result = yield from generator
, используя return result
:
>>> def bar():
... result = yield from gen()
... print('gen() returned', result)
...
>>> next(bar(), None)
gen() returned Return value
Эта функция используется в стандартной библиотеке Python; например в библиотеке asyncio
значение StopIteration
используется для передачи результатов Task
, а декоратор @coroutine
использует res = yield from ...
для запуска генератора с оболочкой или ожидаемого и передачи через возвращаемое значение.
Итак, с точки зрения PEP-8, для генераторов существует две возможности:
Вы используете return
для раннего выхода из генератора, скажем, в цикле с if
. Используйте return
, не нужно добавлять None
:
def foo():
while bar:
yield ham
if spam:
return
Вы используете return <something>
для выхода и для установки StopIteration.value
. Используйте return <something>
последовательно во всем генераторе, даже при возврате None
:
def foo():
for bar in baz:
yield bar
if spam:
return 'The bar bazzed the spam'
return None