이터러블(Iterable)이란?
이터러블은 내장 함수 iter()에 전달되었을 때 이터레이터를 생성하는 객체로 정의할 수 있습니다. 객체가 이터러블이 되기 위해서는 몇 가지 조건을 충족해야 하는데, 해당 클래스의 객체가 __len__과 __getitem__이라는 두 개의 인스턴스 메서드를 정의하고 있어야 합니다. 이 조건들을 충족하는 객체는 iter() 메서드에 전달될 때 이터레이터를 생성합니다.
다음 예제를 통해 이터러블의 개념을 살펴보겠습니다.
string = "Tutorialspoint"
for char in string:
print(char)출력 결과
T u t o r i a l s p o i n t
위 코드는 지정된 인덱스 위치의 요소를 반환하는 __getitem__(index) 메서드를 활용합니다. 따라서 위 코드의 실제 동작 과정은 다음과 같습니다.
- 인덱스 0부터 시작합니다.
string.__getitem__(index)를 호출합니다.- IndexError가 발생하면 반복을 중지합니다.
- 루프 본문을 실행합니다.
- 인덱스를 증가시킨 후 2번 단계로 돌아갑니다.
이터레이터(Iterator)란?
이터레이터는 내부 상태 변수를 통해 반복 진행 상황을 추적하는 객체입니다. 여기서 중요한 점은 반복이 마지막 항목을 지나쳤을 때 상태 변수가 0으로 초기화되지 않고, 대신 StopIteration() 예외를 발생시켜 반복의 끝을 알린다는 것입니다. 이러한 특성 때문에 이터레이터의 요소는 한 번만 순회할 수 있으며, 아래 예제에서 그 차이를 확인할 수 있습니다.
my_list = ['itemOne', 'TutorialsPoints']
iterators_of_some_list = iter(my_list)
for i in iterators_of_some_list:
print(i)
for j in iterators_of_some_list: # 동작하지 않음
print(j)
# 하지만
for k in my_list:
print(k)
for l in my_list: # 정상적으로 동작함
print(l)출력 결과
itemOne TutorialsPoints itemOne TutorialsPoints itemOne TutorialsPoints
위 코드가 이렇게 동작하는 이유는 이터레이터에 대해 iter() 메서드를 호출하면 자기 자신을 반환하기 때문입니다. 이터레이터는 현재 상태를 기억하므로, 이미 소진된 이터레이터를 다시 순회하려고 하면 더 이상 출력할 값이 없습니다. 반면 리스트와 같은 이터러블은 매번 새로운 이터레이터를 생성하므로 몇 번이든 반복해서 순회할 수 있습니다. 즉, 위 코드에는 "for" 루프와 유사한 방식으로 반복을 종료하는 구현이 포함되어 있는 셈입니다.