이터레이터는 ‘반복 가능한 객체’를 순회하는 도구다. 이 ‘반복 가능한 객체’란 리스트, 튜플, 문자열과 같이 여러 요소를 포함하고 있는 데이터 구조를 말한다. 이터레이터는 이러한 데이터 구조의 요소를 하나씩 꺼내서 사용할 수 있게 해준다.
이터레이터 객체는 __iter__()
와 __next__()
라는 두 가지 메서드를 구현하고 있다. __iter__()
메서드는 이터레이터 객체 자체를 반환하며, __next__()
메서드는 컬렉션의 다음 요소를 반환한다. 만약 모든 요소가 순회되어 더 이상 반환할 요소가 없다면, StopIteration
예외를 발생시켜 순회가 끝났음을 알린다.
예를 들어, 리스트에 대한 이터레이터를 생성하고 요소를 순회하는 코드는 다음과 같다.
my_list = [1, 2, 3, 4, 5]
my_iterator = iter(my_list)
while True:
try:
item = next(my_iterator)
print(item)
except StopIteration:
break
제너레이터는 이터레이터를 더 쉽게 생성할 수 있는 방법을 제공하는 특별한 종류의 이터레이터다. 제너레이터는 일반적인 함수처럼 정의되지만, return
대신 yield
키워드를 사용해 값을 반환한다. yield를 만나면 함수의 실행이 일시 중지되고, 해당 값을 호출자에게 반환한다. 다음 호출 때에는 중지된 지점부터 실행을 재개한다.
제너레이터는 메모리를 효율적으로 사용할 수 있게 해주기 때문에, 대용량 데이터를 처리하는 데 아주 유용하다. 모든 데이터를 메모리에 로드하지 않고, 필요할 때마다 데이터를 생성하고 반환할 수 있기 때문이다.
피보나치 수열을 생성하는 제너레이터 함수를 만들어보자. 이 함수는 yield
를 사용해 피보나치 수열의 각 항을 순서대로 반환한다.
def fibonacci_generator(n):
a, b = 1, 1
for _ in range(n):
yield a
a, b = b, a + b
# 피보나치 수열의 처음 10개 항을 출력
for num in fibonacci_generator(10):
print(num)
이터레이터는 반복 가능한 객체의 요소를 하나씩 접근하는 방법을 제공하는 반면, 제너레이터는 이터레이터를 더 쉽게 생성할 수 있는 방법을 제공한다. 제너레이터는 yield
키워드를 사용해 함수의 실행을 일시 중지하고 값을 반환할 수 있다. 이렇게 하면 함수는 중지된 상태에서 다시 시작할 수 있으므로, 대용량 데이터를 효율적으로 처리할 수 있다.