이터레이터, 이터러블, 이터레이션?
3 minute read

이 글은 python - What exactly are iterator, iterable, and iteration? - Stack Overflow를 번역하면서 보충, 정리한 것임을 먼저 밝힙니다.

Iteration

어떤 객체의 원소에 하나씩 차례로 접근하는 것. 명시적으로든 암묵적으로든 반복문을 사용해 객체의 여러 원소에 하나하나 접근하면 그것은 이터레이션(iteration)이다.

Iteration | Definition of Iteration by Merriam-Webster
the repetition of a sequence of computer instructions a specified number of times or until a condition is met

이터레이션은 그냥 말 그대로 반복이다. 특정 횟수만큼 또는 어떤 조건이 만족될 때까지 명령을 반복하는 것.

Iterable & Iterator

파이썬의 iterable과 iterator은 특별한 의미를 가지고 있다.

Iterable의 특징은 일단 내부 원소에 하나씩 차례로 접근할 수 있다는 점이다. 따라서 이터러블은 for item in iterable: ...의 문법을 사용할 수 있다. 그런데 이러한 문법을 수행할 수 있는 것은 이터러블이 __iter__ 메소드를 가지고 있는 객체이기 때문이다. 이것이 이터러블의 좀 더 엄밀한 정의이다. 그리고 이 __iter__ 메소스가 하는 일은 iterator를 반환하는 것이다.

Iterator__next__ 메소드로 데이터를 순차적으로 호출할 수 있는 객체이다. 즉 실제로 루프를 돌면서 반복 도중에 현재 위치가 어디인지를 기억하는 것은 이터레이터이다. 이터레이터는 __iter__ 메소드도 가지고 있는데, 실행할 경우 자기자신이 반환된다.

보통은 파이썬에서 for 루프나, map, list comprehension을 사용하면, Iterator__next__ 메소드가 자동으로 호출되고 iteration 과정을 수행한다.

아래는 코드 예시이다.

>>> s = 'cat'     # s는 이터러블이다.
                  # s는 변경이 불가능한(immutable) 문자열(str) 객체이다.
                  # s는 상태(state)를 가지지 않는다.
                  # s는 __getitem__ 메소드를 가진다.
                  
>>> next(s)
TypeError: 'str' object is not an iterator

s는 이터러블이지 이터레이터가 아니기 때문에 next 메소드를 쓸 수 없다. iter 메소드를 사용해면 이터러블로 이터레이터를 만들 수 있다.

>>> t = iter(s)   # t는 이터레이터다.
                  # t는 상태(state)를 가지고 있다.
                  # t는 __next__ 메소드와 __iter__ 메소드를 가진다.

>>> type(s)       
# <class 'str'>

>>> type(t)
# <class 'str_iterator'>

iter을 통해 이터레이터 타입의 객체 t를 만들었다.

>>> next(t)       # next() 함수는 현재값을 반환하고, 다음 상태로 넘어간다.
'c'
>>> next(t)
'a'
>>> next(t)
't'
>>> next(t)
Traceback (most recent call last):
...
StopIteration

이터레이터의 __iter__ 메서드는 이터레이터 객체 자신을 돌려준다 (self iterable).

>>> iter(t) is t 
True

파이썬 도큐먼트는 iterable, iterator을 다음과 같이 자세하게 정의하고 있다. (최근에 파이썬 도큐먼트의 한국어판이 드디어 번역이 완료되어 공개되었다! 감사합니다 :raised_hands:)

iterable (이터러블)
멤버들을 한 번에 하나씩 돌려줄 수 있는 객체. 이터러블의 예로는 모든 (list, str, tuple 같은) 시퀀스 형들, dict 같은 몇몇 비시퀀스 형들, 파일 객체들, __iter__() 나 시퀀스 개념을 구현하는 __getitem__() 메서드를 써서 정의한 모든 클래스의 객체들이 있다. 이터러블은 for 루프에 사용될 수 있고, 시퀀스를 필요로 하는 다른 많은 곳 (zip(), map(), …) 에 사용될 수 있다. 이터러블 객체가 내장 함수 iter()에 인자로 전달되면, 그 객체의 이터레이터를 돌려준다. 이 이터레이터는 값들의 집합을 한 번 거치는 동안 유효하다. 이터러블을 사용할 때, 보통은 iter()를 호출하거나, 이터레이터 객체를 직접 다룰 필요는 없다. for 문은 이것들을 여러분을 대신해서 자동으로 해주는데, 루프를 도는 동안 이터레이터를 잡아둘 이름 없는 변수를 만든다.

iterator (이터레이터)
데이터의 스트림을 표현하는 객체. 이터레이터의 __next__() 메서드를 반복적으로 호출하면 (또는 내장 함수 next() 로 전달하면) 스트림에 있는 항목들을 차례대로 돌려준다. 더 이상의 데이터가 없을 때는 대신 StopIteration 예외를 일으킨다. 이 지점에서, 이터레이터 객체는 소진되고, 이후의 모든 __next__() 메서드 호출은 StopIteration 예외를 다시 일으키기만 한다. 이터레이터는 이터레이터 객체 자신을 돌려주는 __iter__() 메서드를 가질 것이 요구되기 때문에, 이터레이터는 이터러블이기도 하고 다른 이터러블들을 받아들이는 대부분의 곳에서 사용될 수 있다. 중요한 예외는 여러 번의 이터레이션을 시도하는 코드다. (list 같은) 컨테이너 객체는 iter() 함수로 전달하거나 for 루프에 사용할 때마다 새 이터레이터를 만든다. 이런 것을 이터레이터에 대해서 수행하려고 하면, 지난 이터레이션에 사용된 이미 소진된 이터레이터를 돌려줘서, 빈 컨테이너처럼 보이게 만든다.


Notes :memo:

Recent Posts

Content Preserving Text Generation with Attribute Controls
Matching Networks for One Shot Learning
Pointer Networks
Get To The Point: Summarization with Pointer-Generator Networks
Learning Discourse-level Diversity for Neural Dialog Models using Conditional Variational Autoencoders