Consider the following code:
from itertools import chain
lst = ['a', 1, 2, 3, 'b', 4, 5, 'c', 6]
def nestedForLoops():
it = iter(lst)
for item0 in it:
if isinstance(item0, str):
print(item0)
else:
# this shouldn't happen because of
# 1. lst[0] is a str, and
# 2. line A
print(f"this shouldn't happen: {item0=}")
pass
for item1 in it:
if not isinstance(item1, int):
break
print(f'\t{item1}')
else: # no-break
# reached end of iterator
return
# reached a str
assert isinstance(item1, str)
it = chain(item1, it) # line A
nestedForLoops()
I was expecting it to print
a
1
2
3
b
4
5
c
6
but instead it printed
a
1
2
3
this shouldn't happen: item0=4
this shouldn't happen: item0=5
c
this shouldn't happen: item0=6
I wrote what I thought was equivalent code using while
loops instead of for loops:
from itertools import chain
lst = ['a', 1, 2, 3, 'b', 4, 5, 'c', 6]
def nestedWhileLoops():
it = iter(lst)
while True:
try:
item0 = next(it)
except StopIteration:
break
if isinstance(item0, str):
print(item0)
else:
# this shouldn't happen because of
# 1. lst[0] is a str, and
# 2. line B
print(f"this shouldn't happen: {item0=}")
pass
while True:
try:
item1 = next(it)
except StopIteration:
# reached end of iterator
return
if not isinstance(item1, int):
break
print(f'\t{item1}')
# reached a str
assert isinstance(item1, str)
it = chain(item1, it) # line B
nestedWhileLoops()
and this while
loop version does print what I expected, namely
a
1
2
3
b
4
5
c
6
So why does nestedForLoops
behave differently than nestedWhileLoops
?