Ответ 1
Здесь нет ничего плохого в протоколе или в теории, что помешало бы вам писать такой код. Измученный итератора it
будет бросать StopIteration
на каждом последующем вызове it.__next__
, поэтому for
цикла технически не будет возражать, если вы исчерпывают итератор с next
/__next__
вызова в теле цикла.
Я не советую писать такой код, потому что о программе будет очень сложно рассуждать. Если сценарий становится немного более сложным, чем то, что вы показываете здесь, по крайней мере, мне нужно было бы просмотреть некоторые входные данные ручкой и бумагой и выяснить, что происходит.
Фактически, ваш фрагмент кода, возможно, даже не ведет себя так, как вы думаете, он ведет себя, предполагая, что вы хотите напечатать каждое число, которому предшествует четное число.
>>> b = [1, 2, 4, 7, 8]
>>> a = iter(b)
>>> for x in a:
...: if x%2 == 0:
...: print(next(a, 'stop'))
4
stop
Почему пропускается 7
хотя ему предшествует четное число 4
?
>>>> a = iter(b)
>>>> for x in a:
...: print('for loop assigned x={}'.format(x))
...: if x%2 == 0:
...: nxt = next(a, 'stop')
...: print('if popped nxt={} from iterator'.format(nxt))
...: print(nxt)
...:
for loop assigned x=1
for loop assigned x=2
if popped nxt=4 from iterator
4
for loop assigned x=7
for loop assigned x=8
if popped nxt=stop from iterator
stop
Оказывается, x = 4
никогда не назначается циклом for
потому что явный next
вызов вытолкнул этот элемент из итератора до того, for
цикл for
снова смог взглянуть на итератор.
Это то, что я не хотел бы прорабатывать детали при чтении кода.
Если вы хотите перебрать итератора (включая итераторы) в " (element, next_element)
" пар, использовать pairwise
рецепт от itertools
документации.
from itertools import tee
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return zip(a, b)
Демо-версия:
>>> b = [1,2,3,4,5,6,7]
>>> a = iter(b)
>>>
>>> for x, nxt in pairwise(a): # pairwise(b) also works
...: print(x, nxt)
1 2
2 3
3 4
4 5
5 6
6 7
В общем, itertools
вместе со своими рецептами предоставляет множество мощных абстракций для написания читаемого кода, связанного с итерациями. Еще больше полезных помощников можно найти в модуле more_itertools
, включая реализацию pairwise
.