[Python] Iterator, Generator 정리
Language/Python

[Python] Iterator, Generator 정리

뉴비뉴 2025. 12. 26.

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

Iterator란 무엇인가?

https://www.naukri.com/code360/library/iterators-and-generators-in-python

개념

  • iterator는 순차적으로 값을 하나씩 반환하는 객체

Iterator가 되기 위한 조건

  1. __iter__() 메서드: 자기 자신(iterator 객체)을 반환
  2. __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란 무엇인가?

https://www.naukri.com/code360/library/iterators-and-generators-in-python

개념

  • 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

 

댓글

💲 추천 글