yield
사용법
yield
는 제네레이터를 정의하기 위해 function에서 사용되는 파이썬의 키워드이다.
참고로 제너레이터는 실행을 잠깐 멈추고 결과를 리턴한 다음 다시 제너레이터를 호출할 때 멈췄던 위치에서 실행을 재개할 수 있는 특수한 종류의 함수이다.
즉, 값을 한꺼번에 생성하여 메모리에 저장할 필요가 없이 필요할 순간마다 값을 생성할 수 있다.
다음은 피보나치 수열을 생성할 때 yield
을 사용하는 제너레이터 함수의 예이다.
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
이 코드를 실행시켜보자.
fib = fibonacci()
for i in range(10):
print(next(fib))
그럼 다음과 같은 결과를 얻는다.
0
1
1
2
3
5
8
13
21
34
위 예는 설명을 위한 간단한 코드라서 메모리를 많이 차지하지 않는다.
yield
가 유용한 한 가지 상황은 한 번에 어떤 시퀀스를 생성할 때 많은 메모리를 소모할 경우이다.
yield
를 사용한 제너레이터 함수를 만들면 각 값을 필요할 때마다 생성해서 시퀀스 전체를 메모리에 모두 저장할 필요가 없어진다.
메모리 사용량 비교
yield
을 살펴보는 김에 메모리 사용량을 비교해보자.
먼저 같은 역할을 하는 코드이지만 yield
을 사용하는 버전과 아닌 버전을 살펴보자.
def fibonacci_list(n):
fibonacci = [0, 1]
for i in range(2, n):
fibonacci.append(fibonacci[-1] + fibonacci[-2])
return fibonacci[:n]
def fibonacci_generator(n):
a, b = 0, 1
for i in range(n):
yield a
a, b = b, a + b
두 코드 모두 피보나치 수열을 출력하는 코드이다.
먼저 나온 코드는 yield
을 사용하지 않은 버전이고 아래 코드는 사용한 버전이다.
두 코드를 비교할 때 비슷한 환경을 만들어주기 위해 yield
을 사용한 코드를 본문에 있는 코드에서 약간 바꾸었다.
메모리 사용을 비교하는 코드를 완성시켜보자.
import psutil
def fibonacci_list(n):
fibonacci = [0, 1]
for i in range(2, n):
fibonacci.append(fibonacci[-1] + fibonacci[-2])
return fibonacci[:n]
def fibonacci_generator(n):
a, b = 0, 1
for i in range(n):
yield a
a, b = b, a + b
if __name__ == '__main__':
n = 100000
mem_before_list = psutil.Process().memory_info().rss / 1024 / 1024
fibonacci_list(n)
mem_after_list = psutil.Process().memory_info().rss / 1024 / 1024
print(f"Memory used by list function: {mem_after_list - mem_before_list} MB")
mem_before_gen = psutil.Process().memory_info().rss / 1024 / 1024
gen = fibonacci_generator(n)
for i in gen:
pass
mem_after_gen = psutil.Process().memory_info().rss / 1024 / 1024
print(f"Memory used by generator function: {mem_after_gen - mem_before_gen} MB")
psutil
을 사용하여 간단하게 구현할 수 있다.
이 코드를 돌린 결과는 다음과 같다.
파일 이름을 test.py
로 저장하고 코드를 실행했을 때 yield
을 사용하면 메모리를 거의 사용하지 않은 것을 확인할 수 있다.
n 값을 200000으로 키운 다음 다시 돌려보자.
결과에서 볼 수 있는 것처럼 코드에서 n
값이 커질수록 리스트 방식에서는 메모리 사용량이 늘어나지만 yield
에서는 큰 변화가 없다.
살펴본 것처럼 yield
을 사용하면 프로그램을 보다 가볍게 만들 수 있으니 적재적소에 잘 활용해보자.
'머신 러닝 > Python' 카테고리의 다른 글
[Python] 재귀 함수(Recursive Function)와 동적 계획법(Memoization) 사용 예제(이항계수) (1) | 2024.01.03 |
---|---|
[Python] 재귀 함수(Recursive Function)와 예제(팩토리얼, 이항계수 계산) (0) | 2024.01.02 |
[ChatGPT] 파이썬으로 챗GPT 텔레그램 봇 직접 만들기 / ChatGPT Telegram Bot using Python (2) | 2023.03.28 |
[KakaoTalk] 파이썬으로 카카오톡 메시지 봇 만들기 (5) | 2023.02.23 |
[Python] 예제를 통해 알아보는 파이썬 멀티프로세싱 / Multi-processing, pool (0) | 2023.02.19 |