이 글은 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을 다음과 같이 자세하게 정의하고 있다. (최근에 파이썬 도큐먼트의 한국어판이 드디어 번역이 완료되어 공개되었다! 감사합니다 )
iterable (이터러블)
멤버들을 한 번에 하나씩 돌려줄 수 있는 객체. 이터러블의 예로는 모든 (list
,str
,tuple
같은) 시퀀스 형들,dict
같은 몇몇 비시퀀스 형들, 파일 객체들,__iter__()
나 시퀀스 개념을 구현하는__getitem__()
메서드를 써서 정의한 모든 클래스의 객체들이 있다. 이터러블은for
루프에 사용될 수 있고, 시퀀스를 필요로 하는 다른 많은 곳 (zip()
,map()
, …) 에 사용될 수 있다. 이터러블 객체가 내장 함수iter()
에 인자로 전달되면, 그 객체의 이터레이터를 돌려준다. 이 이터레이터는 값들의 집합을 한 번 거치는 동안 유효하다. 이터러블을 사용할 때, 보통은iter()
를 호출하거나, 이터레이터 객체를 직접 다룰 필요는 없다.for
문은 이것들을 여러분을 대신해서 자동으로 해주는데, 루프를 도는 동안 이터레이터를 잡아둘 이름 없는 변수를 만든다.
iterator (이터레이터)
데이터의 스트림을 표현하는 객체. 이터레이터의__next__()
메서드를 반복적으로 호출하면 (또는 내장 함수next()
로 전달하면) 스트림에 있는 항목들을 차례대로 돌려준다. 더 이상의 데이터가 없을 때는 대신StopIteration
예외를 일으킨다. 이 지점에서, 이터레이터 객체는 소진되고, 이후의 모든__next__()
메서드 호출은StopIteration
예외를 다시 일으키기만 한다. 이터레이터는 이터레이터 객체 자신을 돌려주는__iter__()
메서드를 가질 것이 요구되기 때문에, 이터레이터는 이터러블이기도 하고 다른 이터러블들을 받아들이는 대부분의 곳에서 사용될 수 있다. 중요한 예외는 여러 번의 이터레이션을 시도하는 코드다. (list 같은) 컨테이너 객체는iter()
함수로 전달하거나for
루프에 사용할 때마다 새 이터레이터를 만든다. 이런 것을 이터레이터에 대해서 수행하려고 하면, 지난 이터레이션에 사용된 이미 소진된 이터레이터를 돌려줘서, 빈 컨테이너처럼 보이게 만든다.
Notes
- iterable, iterator는 파이썬에서 iteration을 가능하게 하는 객체들이다.
- iterable은 iteration을 할 수 있는 객체이고, 직접 iteration을 수행하는 객체는 iterator이다.
- iterable의
__iter__
메소드를 이용하면 iterator 객체를 만들 수 있다. -
for
문은 이걸 자동으로 해주기 때문에 명시적으로__iter__
메소드를 호출할 필요가 없다.