2019.03.28 - python-Iterator

1 분 소요

Iterator

Iterator의 기본 개념

이터레이터(iterator)란 무엇인가? 이는 next()를 호출할 때 다음값을 생성해내는 상태를 가진 헬퍼 객체이다. 이터레이터 객체를 확인하는 가장 쉬운 방법은 dir()메서드를 활용해 객체 안에 __iter__가 존재하는 지를 확인하는 것이다.

또한 이터레이터는 데이터 스트림을 나타내는 객체라고도 할 수 있다. 이터레이터 타입의 객체들은 next()메서드를 통해 반복 호출 할 수 있다. 만약 next()메서드를 통해 모든 데이터를 호출하고 나면 StopIteration이라는 에러가 발생한다. 다시 말해 Iterator의 특징을 요약하면 다음과 같다.

  • Iterator는 next()메서드를 통해 값을 하나씩 반환
  • next()로 데이터를 불러올 수 없으면 StopIteration이라는 에러를 발생시킴

Iterator객체를 동작할 때는 next()메서드를 사용한다. 이러한 동작 방식을 Lazy evaluation(게으른 연산)이라고 한다. 이 Lazy evaluation은 필요한 경우에만 객체를 불러와 사용하는데, 불러오기 전까지는 메모리 공간을 사용하지 않으므로 다른 객체가 메모리를 사용할 수 있게 된다.

게으른 팩토리 (a lazy factory)

이 게으른 팩토리는 이터레에터와 제너레이터(Generator)에 바탕이 되는 개념이다.

바깥에서보면 이터레이터는 값을 요청할때까지 유휴(idle) 상태인 게으른 팩토리처럼 보인다. 이는 하나의 값을 생성한 후에 다시 유휴 상태가 된다.

Iterator Customizing

Iterator를 만들때는 Iter()를 사용하면 쉽게 Iterator로 만들 수 있지만 클래스를 사용하여 customizing 할 수 있다.

class MyIter:
    def __ini__(self, li):
        self.container = li
        self.index = 0
	
    def __iter__(self):  # iter함수를 호출했을때, __iter__를 호출한다. 인터페이스 역할
        return self
	
    def __next__(self):  # next함수를 호출할 때, __next__를 호출한다. StopIeration에러 조건만 있으면 내용 수정 가능
        if self.index >= len(self.container):
            raise StopIteration
        ret = self.container[self.index]
        self.index += 1
        return ret
    
it_obj = MyIter([1, 2, 3, 4, 5])
type(it_obj)
>>> __main__.MyIter
it = iter(it_obj)
type(it)
>>> __main__.MyIter

Iterator 와 Iterable

Iterable 객체는 요소를 한 번에 하나씩 가져올 수 있는 객체이고, 이터레이터는 __next__ 메서드를 사용해서 차례대로 값을 꺼낼 수 있는 객체이다. Iterator는 next()를 사용하여 하나씩 호출 할 수 있는 객체인 것이다. 이 Iterable 객체들은 iter()메서드를 통해 iterator 객체로 사용할 수 있다.

Iterator unpacking

이터레이터와 제너레이터(Generator) 변수 여러개에 값을 저장하는 언패킹(unpacking)이 가능하다

a, b, c = Iterator()

반복문에서의 Iterator

잘 생각해보면 우리가 흔히 사용하는 for문에서 list, str 등을 사용하여 그 안에 객체들을 순회하여 사용해 왔다. 이렇게 for문안에 iterable한 객체들을 사용할 때 따로 iterator 객체로 만들지 않고 사용할 수 있는 이유는, for문을 사용할 때 파이썬 내부에서 임시로 iterable객체들을 iterator로 변환해주기 때문이다.

The for statement does that automatically for you, creating a temporary unnamed variable to hold the iterator for the duration of the loop.