파이썬 고급편 시리즈
Advanced Python Programming
게으른 평가 (Lazy Evaluation)
제너레이터와 이터레이터 활용
메모리 효율적인 파이썬 프로그래밍의 핵심 개념을 마스터해보세요
개요 및 중요성
이번 강의에서는 파이썬의 제너레이터(Generator)와 이터레이터(Iterator)에 대해 깊이 있게 다룹니다. 이들은 파이썬에서 메모리 효율적인 프로그래밍을 가능하게 하는 핵심 개념입니다.
특히 대용량 데이터를 다루거나 무한 시퀀스를 생성할 때, 제너레이터와 이터레이터를 활용하면 메모리 사용량을 극적으로 줄이면서도 효율적인 데이터 처리가 가능합니다.
💡 핵심 포인트
게으른 평가(Lazy Evaluation)를 통해 필요한 시점에만 값을 생성하여 메모리와 성능을 최적화할 수 있습니다.
이터레이터 프로토콜 이해하기
파이썬의 이터레이터 프로토콜은 __iter__()
와 __next__()
메서드로 구성됩니다. 이를 구현하면 객체를 반복 가능하게 만들 수 있습니다.
class CountDown:
"""지정된 숫자부터 0까지 카운트다운하는 이터레이터"""
def __init__(self, start):
self.start = start
def __iter__(self):
return self
def __next__(self):
if self.start <= 0:
raise StopIteration
self.start -= 1
return self.start + 1
# 사용 예시
countdown = CountDown(5)
for num in countdown:
print(num) # 5, 4, 3, 2, 1 출력
위 코드에서 __iter__()
는 이터레이터 객체를 반환하고, __next__()
는 다음 값을 반환하거나 더 이상 값이 없으면 StopIteration
예외를 발생시킵니다.
제너레이터와 yield 키워드
제너레이터는 yield
키워드를 사용하는 함수로, 이터레이터보다 훨씬 간단하게 구현할 수 있습니다. 함수가 호출될 때마다 이전 상태를 기억하고 있다가 다음 값을 생성합니다.
def countdown_generator(start):
"""yield를 사용한 간단한 카운트다운 제너레이터"""
while start > 0:
yield start
start -= 1
# 사용 예시
gen = countdown_generator(5)
for num in gen:
print(num) # 5, 4, 3, 2, 1 출력
# 무한 시퀀스 제너레이터
def infinite_numbers():
"""무한히 증가하는 숫자를 생성"""
num = 0
while True:
yield num
num += 1
🚀 제너레이터의 장점
- • 메모리 효율성: 모든 값을 메모리에 저장하지 않음
- • 지연 평가: 필요한 시점에만 값을 계산
- • 무한 시퀀스 생성 가능
- • 간단한 구문으로 복잡한 이터레이션 로직 구현
메모리 효율성과 성능 비교
리스트 컴프리헨션과 제너레이터 표현식의 메모리 사용량 차이를 살펴보겠습니다. 큰 데이터셋을 다룰 때 이 차이는 매우 중요합니다.
import sys
# 리스트 컴프리헨션 - 모든 값을 메모리에 저장
list_comp = [x * x for x in range(1000000)]
print(f"리스트 메모리 사용량: {sys.getsizeof(list_comp):,} bytes")
# 제너레이터 표현식 - 값을 필요할 때마다 생성
gen_expr = (x * x for x in range(1000000))
print(f"제너레이터 메모리 사용량: {sys.getsizeof(gen_expr):,} bytes")
# 출력 예시:
# 리스트 메모리 사용량: 8,448,728 bytes
# 제너레이터 메모리 사용량: 104 bytes
🔴 리스트 컴프리헨션
- • 모든 값을 한 번에 메모리에 로드
- • 빠른 인덱스 접근 가능
- • 큰 데이터셋에서 메모리 부족 위험
🟢 제너레이터 표현식
- • 필요할 때마다 값을 생성
- • 매우 적은 메모리 사용
- • 무한 시퀀스 처리 가능
itertools 모듈 활용
파이썬의 itertools
모듈은 효율적인 반복을 위한 강력한 도구들을 제공합니다.
import itertools
# count: 무한 산술 수열
counter = itertools.count(10, 2) # 10부터 2씩 증가
for i, num in enumerate(counter):
if i >= 5:
break
print(num) # 10, 12, 14, 16, 18
# cycle: 무한 반복
colors = itertools.cycle(['red', 'green', 'blue'])
for i, color in enumerate(colors):
if i >= 7:
break
print(f"항목 {i}: {color}")
# chain: 여러 이터러블 연결
list1 = [1, 2, 3]
list2 = [4, 5, 6]
chained = itertools.chain(list1, list2)
print(list(chained)) # [1, 2, 3, 4, 5, 6]
실습: 피보나치 수열 제너레이터
이번 강의에서 학습한 내용을 바탕으로 피보나치 수열을 생성하는 메모리 효율적인 제너레이터를 구현해보겠습니다. 이 예제는 제너레이터의 상태 보존과 지연 평가의 특성을 잘 보여줍니다.
def fibonacci_generator(n=None):
"""
피보나치 수열을 생성하는 제너레이터
Args:
n (int, optional): 생성할 피보나치 수의 개수.
None이면 무한히 생성
Yields:
int: 피보나치 수
"""
a, b = 0, 1
count = 0
while n is None or count < n:
yield a
a, b = b, a + b
count += 1
def fibonacci_list(n):
"""비교를 위한 일반 함수 (리스트 반환)"""
result = []
a, b = 0, 1
for _ in range(n):
result.append(a)
a, b = b, a + b
return result
if __name__ == "__main__":
print("=== 제너레이터 사용 ===")
fib_gen = fibonacci_generator(10)
print("처음 10개의 피보나치 수:")
for i, fib in enumerate(fib_gen):
print(f"F({i}) = {fib}")
print("\n=== 메모리 사용량 비교 ===")
import sys
fib_gen_large = fibonacci_generator(1000)
fib_list_large = fibonacci_list(1000)
print(f"제너레이터 메모리: {sys.getsizeof(fib_gen_large)} bytes")
print(f"리스트 메모리: {sys.getsizeof(fib_list_large):,} bytes")
코드 실행 방법 및 결과
위 코드를 실행하면 다음과 같은 결과를 확인할 수 있습니다:
F(1) = 1
F(2) = 1
F(3) = 2
F(4) = 3
F(5) = 5
F(6) = 8
F(7) = 13
F(8) = 21
F(9) = 34
마무리
이번 강의에서는 파이썬의 제너레이터와 이터레이터를 통한 게으른 평가(Lazy Evaluation)의 핵심 개념을 다뤘습니다. yield
키워드를 사용한 제너레이터는 메모리 효율성과 성능 최적화에 큰 도움이 됩니다.
🎯 핵심 요약
- • 이터레이터 프로토콜:
__iter__()
와__next__()
메서드로 반복 가능한 객체 구현 - • 제너레이터:
yield
키워드로 간단하게 이터레이터 생성 - • 메모리 효율성: 필요한 시점에만 값을 생성하여 메모리 사용량 최소화
- • 무한 시퀀스: 메모리 제한 없이 무한한 데이터 스트림 처리 가능
- • itertools 모듈: 고급 이터레이션 패턴을 위한 유용한 도구들
다음 강의에서는 컨텍스트 매니저(Context Managers)와 with
구문을 통한 리소스 관리의 효율화에 대해 학습하겠습니다. 파일 처리, 네트워크 연결 등에서 안전하고 깔끔한 코드 작성법을 알아보세요!
'개발 언어 > Python' 카테고리의 다른 글
4강: 파이썬 객체 생성의 비밀: 메타클래스 들여다보기 (0) | 2025.05.27 |
---|---|
3강: 파이썬 고급 - with 구문 마스터하기: 리소스 관리의 효율화 (0) | 2025.05.27 |
파이썬 고급 1강: 데코레이터의 마법: 함수와 클래스 변경하기 (3) | 2025.05.26 |
파이썬 웹 개발 강의: Django와 Flask 배우기 (2) | 2025.05.24 |
PyUIBuilder: Python GUI 개발의 혁신적인 도구 (8) | 2025.05.23 |