파이썬 yield 마스터하기: 제너레이터 vs return 실전 가이드
파이썬 yield 마스터하기: 제너레이터 vs return 실전 가이드
파이썬 yield란 무엇인가?
yield 키워드는 return처럼 동작하지만, 값을 즉시 반환하는 대신 제너레이터 객체를 반환하여 반복 가능하게 만듭니다. yield를 포함한 함수가 호출되면, 첫 yield 문에서 실행이 일시 중지되고 제너레이터와 함께 호출자에게 제어권이 돌아갑니다. 이후 next() 호출이나 for 루프로 실행을 재개하여 다음 값을 산출합니다.
핵심 요약
- yield는 제너레이터를 생성해 지연 평가(lazy evaluation)를 가능하게 합니다.
- 제너레이터는 대용량 또는 무한 시퀀스에 메모리 효율적입니다.
- 제너레이터 읽기는
for-in, list(), next()로 가능.
- 한 번 소진된 제너레이터는 재사용 불가; 함수를 다시 호출해야 함.
문법
yield expression
실전 예제: 간단한 yield
def test_yield():
yield "Welcome to Guru99 Python Tutorials"
output = test_yield()
print(output)
출력: <generator object test_yield at 0x...>
제너레이터 객체가 산출된 값을 보관합니다. 접근하려면 반복:
for value in output:
print(value)
출력: Welcome to Guru99 Python Tutorials
제너레이터 설명
제너레이터 함수는 이터러블한 제너레이터 객체를 반환하는 특수 함수입니다. 단일 값을 반환하는 일반 함수와 달리, 제너레이터는 값 시퀀스를 요청될 때만 하나씩 생성하는 지연 방식으로 산출합니다.
제너레이터 함수 만들기
def generator_example():
yield "H"
yield "E"
yield "L"
yield "L"
yield "O"
for letter in generator_example():
print(letter)
출력: H E L L O (각 줄)
일반 함수 vs 제너레이터 함수
# 일반 함수
def normal_test():
return "Hello World"
# 제너레이터 함수
def generator_test():
yield "Hello World"
print(normal_test()) # → Hello World
print(generator_test()) # → <generator object generator_test>
일반 함수는 return에서 종료; 제너레이터는 yield에서 일시 중지하고 제너레이터 객체와 함께 제어권 반환.
제너레이터 소비하기
제너레이터에서 값 가져오기:
for-in 루프
list()로 모든 값 구체화
next()로 수동 단계 진행
예제: 짝수
def even_numbers(n):
for x in range(n):
if x % 2 == 0:
yield x
print(list(even_numbers(10))) # → [0, 2, 4, 6, 8]
for-in 사용
for num in even_numbers(10):
print(num)
출력: 0 2 4 6 8 (각 줄)
next() 사용
gen = even_numbers(10)
for _ in range(6):
try:
print(next(gen))
except StopIteration:
print("제너레이터 끝")
출력: 0 2 4 6 8 제너레이터 끝
제너레이터는 일회용
제너레이터가 완전히 순회되면 소진됩니다. 다시 순회하려면 제너레이터 함수를 다시 호출해야 합니다.
gen = even_numbers(10)
for num in gen:
print(num)
print(list(gen)) # → []
실전 yield: 피보나치 수열
def fibonacci_series(limit):
a, b = 0, 1
count = 0
while count < limit:
yield a
a, b = b, a + b
count += 1
fib = fibonacci_series(7)
for num in fib:
print(num)
출력: 0 1 1 2 3 5 8
yield하는 함수 호출
도우미 함수와 제너레이터로 제곱수 산출:
def square(n):
return n * n
def square_range(n):
for i in range(n):
yield square(i)
for value in square_range(10):
print(value)
출력: 0 1 4 9 16 25 36 49 64 81
yield를 return 대신 쓸 때
- 한 번에 모든 항목을 로드하기 어려운 대용량 또는 스트리밍 데이터 처리.
- 잠재적으로 무한한 시퀀스 생성(예: 지연 파일 리더).
- 대용량 데이터셋의 메모리 사용량과 시작 시간 개선.
- 단순 반환이 아닌 계산 일시 중지 및 재개 필요 시.
yield vs return – 빠른 참조
| Yield | Return |
| 제너레이터 반환; 반복 시 실행 재개 | 함수 종료; 단일 값 즉시 반환 |
각 yield에서 일시 중지, 메모리 절약 | 반환값 메모리 할당 |
| 대용량/무한 시퀀스에 적합 | 작은, 개별 결과에 적합 |
| 대용량 데이터에서 실행 시간 더 빠름 | 거대 데이터 처리 시 오버헤드 발생 가능 |
핵심 요약
- yield는 값이 아닌 제너레이터 객체 생성.
- 제너레이터는 값을 지연 전달해 메모리 사용 최소화.
for-in, list(), next()로 값 읽기.
- 소진되면 재생성해야 재사용 가능.
- 대용량/스트리밍 데이터에서 return보다 yield 우수.