Skip to content

custom iterator with __iter__ in python

원칙: 1. __iter__를 구현하여야 한다. 이 매직 메서드 안에 순회를 위한 인덱스라던가 이것저것을 초기화 하는 코드를 넣으면 좋습니다. 2. __iter__는 반드시 __next__ 매직 메서드를 구현한 객체를 리턴하여야 한다. 3. __next__ 메서드는 컨테이너의 끝에 도달하는 등 순회가 끝났을 때 반드시 StopIteration 에러를 일으켜야만 한다.

예제로 range 비스무리한 커스텀 이터레이터를 만들어보자.

class MyIterator:

    def __init__(self, stop):
        self.currentValue = 0
        self.stop = stop

    def __iter__(self):
        return self

    def __next__(self):
        if self.currentValue >= self.stop:
            raise StopIteration
        result = self.currentValue
        self.currentValue += 1
        return result

my_iterator = MyIterator(5)

for i in my_iterator:
    print(i)

under the hood... 1. for__iter__를 호출한다. 내부적으로 초기화 작업을 수행한다. 2. 순회를 하면서 __next__를 호출한다. 이때 이터레이터는 내부 상태를 바꾸는 작업을 수행한다.

iter, next builtin functions#

그냥 iter__iter__를 실행시켜 이터레이터 오브젝트를 반환받고, next는 이터레이터의 상태를 변화시고 결과값을 받아낸다.

my_iterator = MyIterator(5)
it = iter(my_iterator)
print(it)
print(next(it))  # 0
print(next(it))  # 1
print(next(it))  # 2
print(next(it))  # 3
print(next(it))  # 4
print(next(it))  # raise StopIteration

Unpacking Iterators#

순회를 굳이 하지 않고, 몇개의 원소들을 임의로 분해(혹은 언팩)할 수 있다. 이건 좀 좋은데?

a, b, c, d, e = MyIterator(5)
print(a, b, c, d, e)

Generator which generates iterator-like control block#

generator function - python으로 옮겨감