"yield from iterable" против "return iter(iterable)"
При переносе (внутреннего) итератора часто приходится перенаправлять __iter__
метод к основному повторяемому. Рассмотрим следующий пример:
class FancyNewClass(collections.Iterable):
def __init__(self):
self._internal_iterable = [1,2,3,4,5]
# ...
# variant A
def __iter__(self):
return iter(self._internal_iterable)
# variant B
def __iter__(self):
yield from self._internal_iterable
Есть ли существенная разница между вариантом A и B? Вариант А возвращает объект итератора, который был запрошен через iter()
из внутреннего повторяемого. Вариант B возвращает объект-генератор, который возвращает значения из внутренней итерации. Является ли один или другой предпочтительным по какой-то причине? В collections.abc
yield from
версия используется. return iter()
Вариант - это шаблон, который я использовал до сих пор.
1 ответ
Единственное существенное отличие состоит в том, что происходит, когда исключение вызывается из итерируемого. С помощью return iter()
ваш FancyNewClass
не будет отображаться при отслеживании исключений, тогда как при yield from
будет. Как правило, полезно иметь как можно больше информации о трассировке, хотя могут быть ситуации, когда вы хотите скрыть свою оболочку.
Другие отличия:
return iter
должен загрузить имяiter
от глобальных переменных - это потенциально медленно (хотя вряд ли может существенно повлиять на производительность) и может быть испорчено (хотя любой, кто перезаписывает глобальные переменные, заслуживает того, что они получают).С
yield from
Вы можете вставить другиеyield
выражения до и после (хотя вы могли бы в равной степени использоватьitertools.chain
).Как представлено,
yield from
Форма отбрасывает любое возвращаемое значение генератора (т.е.raise StopException(value)
, Вы можете исправить это, написав вместоreturn (yield from iterator)
,
Вот тест, сравнивающий разборку двух подходов, а также показывающий трассировки исключений: http://ideone.com/1YVcSe
С помощью return iter()
:
3 0 LOAD_GLOBAL 0 (iter)
3 LOAD_FAST 0 (it)
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 RETURN_VALUE
Traceback (most recent call last):
File "./prog.py", line 12, in test
File "./prog.py", line 10, in i
RuntimeError
С помощью return (yield from)
:
5 0 LOAD_FAST 0 (it)
3 GET_ITER
4 LOAD_CONST 0 (None)
7 YIELD_FROM
8 RETURN_VALUE
Traceback (most recent call last):
File "./prog.py", line 12, in test
File "./prog.py", line 5, in bar
File "./prog.py", line 10, in i
RuntimeError