이터레이터/제너레이터

2025. 1. 10.·언어/Python

이터레이션(Iteration)

어떤 자료 구조(예: 리스트, 튜플 등)를 순차적으로 하나씩 꺼내는 과정

이터러블(Iterable)

내부 요소를 하나씩 꺼낼 수 있는 객체

예: 리스트(list), 튜플(tuple), 문자열(str), 딕셔너리(dict), 셋(set), 그리고 사용자 정의 이터러블 클래스 등

이터러블 객체는 내부적으로 __iter__ 메서드를 구현해야 함

 

이터레이터(Iterator)

실제로 값을 하나씩 꺼내는 역할을 하는 객체

내부적으로 __next__ 메서드를 가져야 하며, 이 메서드는 순회할 다음 값을 반환

더 이상 꺼낼 값이 없다면 StopIteration 예외를 발생시켜 이터레이션이 종료됨을 알림

# 리스트(이터러블)를 이터레이터로 만드는 과정
numbers = [1, 2, 3]
iterator = iter(numbers)  # numbers.__iter__() 호출

print(next(iterator))  # iterator.__next__() 호출 → 1
print(next(iterator))  # 2
print(next(iterator))  # 3
print(next(iterator))  # StopIteration 예외 발생

iter(numbers) → 이터레이터를 반환

next(iterator) → 이터레이터에서 다음 요소를 꺼냄

 

사용자 정의 이터레이터

직접 클래스를 정의해서 __iter__()와 __next__() 메서드를 구현하면, 원하는 규칙으로 순회를 제어 가능

class Counter:
    def __init__(self, start, stop):
        self.current = start
        self.stop = stop

    def __iter__(self):
        return self  # 이터레이터 자체를 반환

    def __next__(self):
        if self.current < self.stop:
            val = self.current
            self.current += 1
            return val
        else:
            raise StopIteration

counter = Counter(1, 5)
for num in counter:
    print(num, end=" ")  
# 출력: 1 2 3 4

for num in counter: 구문이 내부적으로 __iter__()로 이터레이터를 얻고, 매 반복마다 __next__()를 호출

StopIteration 예외가 발생하면 for 루프가 종료

--🐢

제너레이터(Generator)

이터레이터를 간편하게 만드는 특별한 함수(혹은 표현식)

일반 함수와 달리, return 대신 yield를 사용하여 데이터를 하나씩 반환(생성)

제너레이터 함수는 호출될 때 함수 전체가 한 번에 실행되지 않고, yield 키워드를 만날 때마다 현재 상태를 기억한 채 값을 하나 내보냄

def simple_generator():
    print("첫 번째 yield 직전")
    yield 1
    print("두 번째 yield 직전")
    yield 2
    print("끝")

gen = simple_generator()
print(next(gen))  # "첫 번째 yield 직전" 출력 후 1 반환
print(next(gen))  # "두 번째 yield 직전" 출력 후 2 반환
print(next(gen))  # "끝" 출력 후 StopIteration 발생

yield를 만나면 값을 반환(중간에 함수가 멈춤)하고, 다음 next()가 호출되면 이전 상태를 이어서 진행

제너레이터 함수는 이터레이터 프로토콜(__iter__, __next__)을 자동으로 구현해 줌

즉, 제너레이터 함수를 호출하면 이터레이터 객체가 반환

 

제너레이터 표현식

# 제너레이터 표현식
gen_exp = (x*2 for x in range(5))

print(gen_exp)  # <generator object <genexpr> at 0x...>

print(next(gen_exp))  # 0
print(next(gen_exp))  # 2
...

제너레이터 표현식은 메모리를 절약하며(필요한 값만 순차적으로 생성), 이터레이터로 활용할 수 있음

 

제너레이터 장점

# 메모리 효율성

한 번에 모든 데이터를 생성하지 않고, 요청될 때(next()가 불릴 때) 하나씩 생성

큰 데이터셋을 다룰 때 특히 유리

# 코드 간결성

이터레이터를 직접 작성하려면 __iter__, __next__를 구현해야 하지만, 제너레이터는 yield만 쓰면 됨

# 지연 평가(Lazy Evaluation)

즉시 모든 요소를 계산하지 않고, 필요한 시점에 값을 생성해 효율적인 계산이 가능

-🐢-

이터레이터/제너레이터 비교

항목 이터레이터(Iterator) 제너레이터(Generator)
구현
방식
__iter__()와 __next__()를 직접 구현 yield 키워드를 사용한 함수나 표현식
사용
편의
상대적으로 복잡 간단하고 가독성 좋음
메모리
사용
로직에 따라 다르지만, 중간 버퍼를 크게 쓸 수 있음 기본적으로 한 번에 하나씩 생성(Lazy), 메모리 효율적
상태
관리
클래스 멤버 변수로 유지 함수의 지역 변수 상태를 자동으로 유지(스택 프레임을 보관)
예외
처리
직접 StopIteration를 raise yield 뒤에 더 이상 코드 없으면 내부적으로 StopIteration 발생 처리
예시 직접 구현한 순회 구조, 복잡한 상태 머신 큰 파일 라인 순회, 무한 시퀀스 등

🐢--

 

 

저작자표시 비영리 변경금지 (새창열림)

'언어 > Python' 카테고리의 다른 글

정규 표현식(Regular Expression)  (0) 2025.01.13
파이썬 타입 어노테이션  (0) 2025.01.11
클로저/데코레이터  (1) 2025.01.09
유니코드 문자열  (1) 2025.01.08
Threading 모듈  (0) 2025.01.07
'언어/Python' 카테고리의 다른 글
  • 정규 표현식(Regular Expression)
  • 파이썬 타입 어노테이션
  • 클로저/데코레이터
  • 유니코드 문자열
우는거북이
우는거북이
  • 우는거북이
    거북이는 울고 있다
    우는거북이
  • 전체
    오늘
    어제
    • 알아보기 (75) N
      • AI (4)
      • 언어 (16)
        • Python (15)
        • C언어 (1)
      • 알고리즘 (7)
      • 백준 (22)
      • 자료구조 (10)
      • 컴퓨터네트워크 (6)
      • 운영체제 (1)
      • 데이터통신 (9) N
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
우는거북이
이터레이터/제너레이터
상단으로

티스토리툴바