Programming

; develop a program

Back-End/Python

[Python] Iterator(반복자)

Clloud_ 2022. 10. 4. 12:11
반응형

이번 포스팅에서는 파이썬의 Iterator(반복자)에 대하여 공부를 해보고자 한다.

 


Iterable/Iterator

Iterable은 반복 조회가 가능한 객체를 말한다.

for in 문을 통해 값들을 순차적으로 제공해주는 객체라고 생각하면 된다. (리스트, 튜플, 셋, 문자열 등)

한번 반복 시마다 값을 하나씩 제공한다.

 

__iter__(self) 특수메소드를 정의하고 Iterator 객체를 반환한다.

__iter__(self) 메소드는 iter(iterable) 함수 호출 시 실행된다.

 

Iterator는 자신을 생성한 iterable의 값을 하나씩 제공하는 객체를 말한다.

 

__next__(self) 특수메소드를 정의하고 iterable의 원소를 순서대로 하나씩 제공한다.

더 이상 제공할 원소가 없을 경우 StopIteration 예외를 발생시킨다.

__next__(self) 특수 메소드는 next(iterator) 호출 시 실행된다.

 

예제

순서 1. 리스트를 생성한다. → Iterable

순서 2. iterable의 __iter__( )를 호출한다. Iterator를 반환

순서 3. iterator의 __next( )를 호출한다. → list의 원소를 하나씩 제공

l = [1, 2, 3]

l_iterator = iter(l)
print(next(l_iterator))
print(next(l_iterator))
print(next(l_iterator))
print(next(l_iterator))

[실행결과]

1
2
3
StopIteration # error 발생

더 이상 제공할 원소가 없으면 StopIteration Exception을 발생시킨다.

 


Iterator(반복자)

for in 문 구현

iterator = nums.__iter__()
while True:
  try:
     num = iterator.__next__()
     print(num)
  except StopIteration:
     break

 

for in 문이 반복자 객체를 순환 조회하는 과정

  1. 반복 조회할 iterable객체의 __iter__( ) 를 호출하여 Iterator를 구한다.
  2. 매 반복마다 Iterator의 __next__( ) 를 호출하여 다음 원소를 조회하고 다음 위치로 이동시키고, 모든 요소를 다 읽을 때까지 반복한다.
  3. 모든 요소를 다 제공하면 Iterator는 StopIteration 예외를 발생시키고 for in문은 반복을 종료한다.

 


Iterable/Iterator 클래스 구현

보통 Iterable 클래스에 Iterator 기능을 추가해서 구현한다.

 

__iter__( ) 메소드 구현

  • Iterable이 구현해야 하는 메소드.
  • Iterator(__next__() 메소드를 가지고 원소를 제공하는 객체)를 반환.

 

__next__( ) 메소드 구현

  • Iterator가 구현해야 하는 메소드
  • 원소를 순차적으로 반환하도록 구현한다.
  • 모든 원소를 반환했을 때는 StopIteration 예외를 발생시킨다.

 

예제

Iterable을 구현

class MyIterable:

    def __init__(self, *args):
        """
        initializer에서 가변인자를 통해 제공해줄 값들을 tuple받아서 저장.
        """
        self.values = args  # tuple

    def __str__(self):
        """제공할 원소들을 가진 tuple을 문자열로 반환"""
        return str(self.values)

    def __iter__(self):
        """원소들을 하나씩 제공할 Iterator객체를 반환"""
        print("MyIterable.__iter__()")
        return MyIterator(self)

 

Iterator를 구현 → MyIterable의 원소들(self.values)을 제공.

class MyIterator:

    def __init__(self, iterable):
        """
        제공해줄 원소를 가지고 있는 Iterable을 인자로 받아서 attribute로 저장.
        몇번째 원소를 제공했는지를 저장할 변수(index)도 저장.
        """
        self.iterable = iterable
        self.index = 0

    def __next__(self):
        """
        next(iterator) 에 의해 호출되는 메소드
        Iterable의 원소를 next()마다 하나씩 제공해주는 메소드
        """
        print("MyIterator.__next__()호출")
        # self.iterable: MyIterable 객체   
        values = self.iterable.values

        if len(values) <= self.index:
            raise StopIteration()

        ret_values = values[self.index]
        self.index += 1
        return ret_values

순서 1. 리스트를 생성한다. → Iterable

순서 2. iterable의 __iter__( )를 호출한다.  Iterator를 반환

순서 3. iterator의 __next( )를 호출한다. → list의 원소를 하나씩 제공

m_iterable = MyIterable(10, 5, 20, 7)

m_iterator = iter(m_iterable)

print(next(m_iterator))
print(next(m_iterator))
print(next(m_iterator))
print(next(m_iterator))
print(next(m_iterator))

[실행결과]

MyIterator.__next__()호출
10
MyIterator.__next__()호출
5
MyIterator.__next__()호출
20
MyIterator.__next__()호출
7
MyIterator.__next__()호출
StopIteration

 


반응형