anati
anati

Reputation: 274

Does for loop call __iter__?

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

Answers (1)

timgeb
timgeb

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

Related Questions