들어가기 전에 파이썬에서 이터레이터(Iterator)는 데이터를 순차적으로 접근하는 객체이고, 제너레이터(Generator)는 이터레이터를 더 쉽게 만들어주는 함수(메서드)인데, 메모리 효율성과 지연 평가(Lazy Evalutation)가 핵심 사용 이유 입니다. 특히 제너레이터는 거대한 데이터셋을 다룰 때 모든 데이터를 한 번에 메모리에 올리지 않고 필요할 때마다 하나씩 생성하여 반환하므로 메모리 사용량을 획기적으로 줄이고, 계산 비용을 낮추어 효율적인 프로그래밍을 가능하게 합니다.
Iterator란 무엇인가?

개념
- iterator는 순차적으로 값을 하나씩 반환하는 객체
Iterator가 되기 위한 조건
- __iter__() 메서드: 자기 자신(iterator 객체)을 반환
- __next__() 메서드: 다음 값을 반환하거나 StopIteration 예외 발생
특징
- 반복 가능한(iterable) 객체로부터 값을 하나씩 가져오는 객체
- 객체(리스트, 튜플 등)의 모든 요소를 순서대로 접근
- 메모리 효율적
기본 사용법
lst = [1,2,3]
it = iter(lst)
print(it) # <list_iterator object at ...>
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
# print(next(it)) # StopIteration 예외 발생
# ---
# for문의 실제 동작 방식
while True:
try:
print(next(something))
except StopIteration:
break
반복 가능 객체 확인
t = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
print(hasattr(t, '__iter__')) # True - 반복 가능 확인
from collections import abc # 객체가 어떤 ‘자료구조적 행동’을 하는지를 정의한 추상 인터페이스 모음
print(isinstance(t, abc,Iterable)) # True - Iterable 상속 확인
Generator란 무엇인가?

개념
- yield 키워드를 사용하여 값을 하나씩 반환하는 특별한 함수
- 호출될 때 제너레이터 객체의 인스턴스를 반환합니다
- 이 함수를 호출하면 Iterator 객체가 생성됨
특징
- __iter__, __next__를 만들 필요 없음(코드가 짧고 직관적) yield로 간단하게 작성
- 상태(state)를 자동으로 기억
- yield에서 멈춘 시점의 지역 변수와 실행 위치를 다음 next() 호출까지 그대로 유지
- 메모리 절약
- 모든 데이터를 미리 생성하지 않고, next() 호출 시점에 데이터를 생성하므로 메모리 부담이 적음 (특히 빅데이터 처리)
- 지연 평가(Lazy Evalutaion)
- 필요한 시점에 값을 생성하여 계산 비용 절감
기본 사용법
def counter(max_num):
num = 0
while num < max_num:
num += 1
yield num # 값을 반환하고 일시정지(강제 중단)
for i in counter(3)
print(i) # 출력: 1,2,3
Iterator vs Generator 비교
Iterator 직접 구현 방식
- 장점: 복잡한 로직 구현 가능
- 단점: 코드 길고, 상태 관리 직접 해야 함
class MyIterator:
def __init__(self):
self.data = [1,2,3]
self.index = 0
def __iter__(self):
return self # 자기 자신 반환
def __next__(self):
if self.index >= len(self.data):
raise StopIteration
value = self.data[self.index]
self.index += 1 # 상태 직접 관리
return value
mi = MyIterator()
for i in mi:
print(i) # 출력: 1,2,3
Generator yield 사용 방식
- 장점: 코드 간결, 상태 자동 관리, 메모리 효율
- 단점: 한 방향으로만 순회 가능
class MyGenerator:
def __init__(self):
self.data = [1,2,3]
def __iter__(self):
for item in self.data:
yield item
# __next__는 Python이 자동 생성
mg = MyGenerator()
for i in mg:
print(i) # 출력: 1,2,3
왜 사용해야 할까?
1. 메모리 효율성
# 리스트 전체를 메모리에 저장
numbers = [i for i in range(1, 100000001)]
total = sum(numbers)
# 한 번에 하나씩만 생성
# 표현식 for 변수 in iterator는 generator expression
numbers = (i for i in range(1, 100000001))
total = sum(numbers) # 거의 메모리 사용 안함
# tip
list: [표현식 for 변수 in iterator]
generator: (표현식 for 변수 in iterator)
tuple: {표현식 for 변수 in iterator}
dict: {표현식: 변수 for 변수 in iterator}
2. 대용량 파일 처리
# 리스트 방식
with open('tim.txt', 'r') as f:
lines = f.readlines() # 파일 전체를 리스트로! 메모리 부족 에러 가능
for line in lines:
process(line)
# iterator 방식
with open('tim.txt', 'r') as f:
for line in f: # f는 iterator! 한 줄씩만 메모리에 올림
process(line)
3. 지연 평가 (Lazy Evaluation) / 성능 향상
- 필요한 값까지만 계산 -> 불필요한 연산 방지
- 긴 시퀀스에서 일부만 사용할 때 매우 효율적
def expensive_calculation():
print("계산 중...")
yield 1
yield 2
yield 3
gen = expensive_calculation()
next(gen)
결론
- 이터레이터는 데이터를 순차적으로 읽는 '원칙'
- 제너레이터는 그 원칙을 메모리 효율적이고 간결하게 구현하는 방법
- 큰 파일 처리, 무한 스트림, 머신러닝 데이터 로딩(e.g. PyTorch, DataLoader) 등에서 성능과 메모리 측면에서 압도적으로 유리하며 주로 제너레이터 방식(함수 또는 제너레이터 표현식)을 선호합니다.
참고
https://stackoverflow.com/questions/2776829/difference-between-pythons-generators-and-iterators
Difference between Python's Generators and Iterators
What is the difference between iterators and generators? Some examples for when you would use each case would be helpful.
stackoverflow.com
'Language > Python' 카테고리의 다른 글
| [FastAPI] 'Unknown Column' 에서 Alembic 사용법 (SQLAlchemy 스키마 동기화) (0) | 2025.06.15 |
|---|---|
| 'google-api-python-client'를 사용한 유튜브 데이터 가져오기 (3) (0) | 2023.09.04 |
| 'google-api-python-client'를 사용한 유튜브 데이터 가져오기 - pandas, argparse (2) (0) | 2023.08.29 |
| 'google-api-python-client'를 사용한 유튜브 데이터 가져오기 - Google Cloud 및 Python 설정 가이드 (1) (0) | 2023.08.24 |
| Python 나무위키 데이터 가져오기 (Pandas, datasets, parquet) (0) | 2023.06.23 |
댓글