Reputation: 274
Look at below sample:
a = [1, 2, 3, 4]
for i in a:
print(a)
a
is the list (iterable) not the iterator.
I'm not asking to know that __iter__
or iter()
convert list to iterator!
I'm asking to know if for loop itself convert list implicitly then call __iter__
for iteration keeping list without removing like iterator?
Since stackoverflow identified my question as possible duplicate:
The unique part is that I'm not asking about for loop as concept nor __iter__
, I'm asking about the core mechanism of for loop and relationship with iter.
Upvotes: 2
Views: 3120
Reputation: 78700
I'm asking to know if for loop itself convert list implicitly then call iter for iteration keeping list without removing like iterator?
The for
loop does not convert the list implicitly in the sense that it mutates the list, but it implicitly creates an iterator from the list. The list itself will not change state during iteration, but the created iterator will.
a = [1, 2, 3]
for x in a:
print(x)
is equivalent to
a = [1, 2, 3]
it = iter(a) # calls a.__iter__
while True:
try:
x = next(it)
except StopIteration:
break
print(x)
Here's proof that __iter__
actually gets called:
import random
class DemoIterable(object):
def __iter__(self):
print('__iter__ called')
return DemoIterator()
class DemoIterator(object):
# it's standard practice to have iterators return
# themselves when for whatever reason __iter__ is called
# on them (however this does not happen in this example)
def __iter__(self):
return self
def __next__(self):
print('__next__ called')
r = random.randint(1, 10)
if r == 5:
print('raising StopIteration')
raise StopIteration
return r
Iteration over a DemoIterable
:
>>> di = DemoIterable()
>>> for x in di:
... print(x)
...
__iter__ called
__next__ called
9
__next__ called
8
__next__ called
10
__next__ called
3
__next__ called
10
__next__ called
raising StopIteration
Upvotes: 12