Data Engineering/python

EP07 | Python 심화 개념 #1 | 이터레이터와 제너레이터

ygtoken 2025. 3. 19. 22:40
728x90

이 글에서 다루는 개념

Python에서 **이터레이터(Iterator)와 제너레이터(Generator)**는 효율적인 반복을 가능하게 하는 중요한 개념입니다.
이번 글에서는 다음 내용을 학습합니다.

  • 이터레이터(Iterator)의 개념과 사용법
  • 이터러블(Iterable) 객체와 iter(), next() 함수
  • 제너레이터(Generator)의 개념과 yield 키워드
  • 이터레이터와 제너레이터의 차이점과 활용 방법

1️⃣ 이터러블(Iterable)과 이터레이터(Iterator)란?

🔹 이터러블(Iterable)

이터러블은 반복 가능한 객체이며, for 문을 사용할 수 있습니다.
대표적인 이터러블 객체: 리스트, 튜플, 문자열, 딕셔너리, 세트

numbers = [1, 2, 3, 4]

for num in numbers:  # 리스트(이터러블) 반복
    print(num)

🔹 이터레이터(Iterator)

이터레이터는 값을 하나씩 반환하는 객체입니다.
이터러블 객체에서 iter() 함수를 사용하여 이터레이터를 생성할 수 있습니다.
next() 함수를 사용하여 다음 값을 가져옵니다.

numbers = [1, 2, 3, 4]
it = iter(numbers)  # 이터레이터 생성

print(next(it))  # 1
print(next(it))  # 2
print(next(it))  # 3
print(next(it))  # 4
# print(next(it))  # 에러 (StopIteration 발생)

📌 이터레이터 특징

  • iter(이터러블)을 사용하면 이터레이터를 생성할 수 있음
  • next(이터레이터)를 호출하면 요소를 하나씩 반환
  • 마지막 요소 이후에 next()를 호출하면 StopIteration 예외 발생

2️⃣ 이터레이터 직접 구현하기

클래스에서 __iter__()와 __next__() 메서드를 구현하면 커스텀 이터레이터를 만들 수 있습니다.

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

    def __iter__(self):
        return self  # 자기 자신을 반환

    def __next__(self):
        if self.current > self.end:
            raise StopIteration  # 반복 종료
        value = self.current
        self.current += 1
        return value

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

📌 이터레이터 구현의 핵심

  1. __iter__() → 객체 자체를 반환
  2. __next__() → 다음 요소 반환 (StopIteration으로 종료)

3️⃣ 제너레이터(Generator)란?

제너레이터는 이터레이터를 더 쉽게 생성하는 방법입니다.
함수 내부에서 yield 키워드를 사용하면 자동으로 이터레이터를 생성합니다.

def my_generator():
    yield 1
    yield 2
    yield 3

gen = my_generator()
print(next(gen))  # 1
print(next(gen))  # 2
print(next(gen))  # 3

📌 제너레이터 특징

  • yield를 사용하여 값을 반환 (함수 종료 없이 상태 유지)
  • 호출될 때마다 이전 상태를 기억하고 next() 호출 시 다음 값을 반환
  • 일반 함수와 달리 메모리를 절약하면서 큰 데이터를 처리 가능

4️⃣ 제너레이터 활용 예제

🔹 1부터 N까지 숫자 생성하는 제너레이터

def count_up(n):
    for i in range(1, n+1):
        yield i

gen = count_up(5)
for num in gen:
    print(num)  # 1, 2, 3, 4, 5

🔹 무한 숫자 생성기 (Lazy Evaluation)

def infinite_counter():
    num = 1
    while True:
        yield num
        num += 1

counter = infinite_counter()
print(next(counter))  # 1
print(next(counter))  # 2

📌 Lazy Evaluation(지연 평가)

  • 제너레이터는 필요할 때마다 값을 생성하여 메모리를 절약할 수 있음
  • 무한 반복문에서도 특정 시점까지만 next()를 호출하면 불필요한 연산을 줄일 수 있음

📌 실전 문제: 이터레이터와 제너레이터 연습하기


문제 1: 리스트를 이터레이터로 변환하고 next()로 요소 가져오기

📌 리스트 [10, 20, 30]을 이터레이터로 변환하고 next()를 사용하여 요소를 하나씩 출력하세요.

numbers = [10, 20, 30]
# 🔽 여기에 코드 작성
numbers = [10, 20, 30]
it = iter(numbers)

print(next(it))  # 10
print(next(it))  # 20
print(next(it))  # 30

문제 2: 커스텀 이터레이터 구현하기

📌 1부터 5까지 숫자를 생성하는 이터레이터 클래스를 구현하세요.

class Counter:
    # 🔽 여기에 코드 작성
class Counter:
    def __init__(self, start, end):
        self.current = start
        self.end = end

    def __iter__(self):
        return self

    def __next__(self):
        if self.current > self.end:
            raise StopIteration
        value = self.current
        self.current += 1
        return value

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

문제 3: 제너레이터를 사용해 1부터 10까지 숫자 생성하기

📌 제너레이터를 사용하여 1부터 10까지의 숫자를 생성하세요.

def count_up():
    # 🔽 여기에 코드 작성
def count_up():
    for i in range(1, 11):
        yield i

gen = count_up()
for num in gen:
    print(num)  # 1, 2, ..., 10

문제 4: 무한 숫자 생성기 만들기

📌 제너레이터를 사용하여 무한히 숫자를 증가시키는 함수를 구현하세요.

def infinite_counter():
    # 🔽 여기에 코드 작성
def infinite_counter():
    num = 1
    while True:
        yield num
        num += 1

counter = infinite_counter()
print(next(counter))  # 1
print(next(counter))  # 2
print(next(counter))  # 3

 

728x90