Python yield

김무성·2022년 2월 25일
0

Python function

목록 보기
2/2

yield 키워드

  • 대부분의 프로그래밍 언어에서 일반적으로 함수는 어떤 결과 값을 return 키워드를 이용해서 반환을 하는 반면 파이썬에서는 yield 키워드를 이용해서 다소 다른 방식으로 결과 값을 제공할 수 있음

Example

  1. 알파벳 A, B, C를 결과 값으로 반환하는 함수를 작성
def return_abc():
  return list("ABC")
위 함수를 yield 키워드를 이용해서 작성해볼까요?

def yield_abc():
  yield "A"
  yield "B"
  yield "C"
  • return 키워드를 사용할 때는 결과값을 딱 한 번만 제공하는 반면 yield 키워드는 결과값을 여러 번 나누어서 제공
  1. for 루프를 사용해서 위 함수를 호출하여 얻은 결과를 화면에 출력
for ch in return_abc():
  print(ch)
A
B
C
for ch in yield_abc():
  print(ch)
A
B
C
  • 함수를 사용하는 측면에서 보면 두 함수는 큰 차이가 없음
  1. 함수를 호출한 결과 값을 바로 출력하여 각 함수가 무엇을 반환하는지 확인
>>> print(return_abc())
['A', 'B', 'C']
>>> print(yield_abc())
<generator object yield_abc at 0x7f4ed03e6040>
  • return_abc() 함수는 리스트(list)를 반환하고 yield_abc() 함수는 제너레이터(generator)를 반환

제너레이터(generator)

  • 파이썬에서 여러 개의 데이터를 미리 만들어 놓지 않고 필요할 때마다 즉석해서 하나씩 만들어낼 수 있는 객체를 의미

Example

  • 위에서 작성한 예제 코드를 알파벳 하나를 만드는데 1초가 걸리도록 수정
import time

def return_abc():
  alphabets = []
  for ch in "ABC":
    time.sleep(1)
    alphabets.append(ch)
  return alphabets

for ch in return_abc():
  print(ch)
# 3초 경과
A
B
C
  • 위 함수를 호출한 결과를 for 루프로 돌려보면 3초가 후가 흐른 후에 A, B, C가 한 번에 출력 됨

  • yield 키워드를 이용해서 동일한 결과 값을 제공하는 함수를 작성

import time

def yield_abc():
  for ch in "ABC":
    time.sleep(1)
    yield ch
    
for ch in return_abc():
  print(ch)
# 1초 경과
A
# 1초 경과
B
# 1초 경과
C
  • 위 함수를 호출한 결과를 for 루프로 돌려보면 1초 후에 A를 출력되고, 또 1초 후에 B를 출력되고, 또 1초 후에 C가 출력 됨

  • 만약에 세개의 알파벳이 아닌 백개, 천개, 만개의 알페벳을 제공해야하는 경우에 첫번째 방식에서는 첫번째 결과값을 얻는데 백초, 천초, 만초가 걸리는 반면, 두번째 방식에서는 항상 일초가 걸림

장점

  • 제너레이터는 결과값을 나누어서 얻을 수 있어 성능 측면에서 큰 이점이 있음

  • 메모리 효율 측면에서도 return 키워드는 모든 결과 값을 메모리에 올려놓아야 하는 반면, yield 키워드는 결과 값을 하나씩 메모리에 올려놓음

  • 제너레이터(generator)는 이러한 특성 때문에 게으 반복자(lazy iterator)라고도 불리는데 이 특성을 잘 활용하면 좀 더 효율적인 프로그램을 작성할 수 있는 경우가 많음

  • 특히 메모리에 한 번에 올리기에는 부담스럽게 대용량의 파일을 읽거나, 스트림 데이터를 처리할 때 상당히 유용하게 사용될 수 있음

무한 데이터 생산

  • 제너레이터를 사용하면 이론적으로 무한한 데이터를 계속해서 만들어낼 수 있음

Example

  • 알파벳 A, B, C를 계속해서 무한하게 제공하는 함수를 작성
def yield_infinite_abc():
  while True:
    yield "A"
    yield "B"
    yield "C"
    
for ch in yield_infinite_abc():
  print(ch)
A
B
C
A
B
C
A
B
C
A
^C
Traceback (most recent call last):
  File "main.py", line 8, in <module>
    print(ch)
KeyboardInterrupt
  • 이 함수를 호출한 결과를 for 루프로 돌리면 A, B, C가 화면에 끊임없이 출력이 됨
    Ctrl + C를 눌러서 빠져나올 수 있다.

  • 데이터를 무한하게 제공하는 함수는 yield 키워드가 없이는 작성하는 것이 거의 불가능 함
    컴퓨터의 물리적인 메모리에는 한계가 있으며 아무리 큰 리스트를 만들더라도 이 한계를 초과할 수는 없기 때문이다.

yield from

  • 리스트를 제너레이터로 변환

Example

def yield_abc():
  for ch in ["A", "B", "C"]:
    yield ch

def yield_abc():
  yield from ["A", "B", "C"]
  • yield from를 사용하면 리스트를 바로 제너레이터로 변환할 수 있음

Generator Comprehension

  • 제너레이터를 만드는 또 다른 방법

  • 리스트 표현식(list comprehension)과 사용 방법이 매우 유사하며 차이점은 리스트 표현식은 대괄호를 사용하고 제너레이터 표현식은 소괄호를 사용

abc = (ch for ch in "ABC")

print(abc)

for ch in abc:
  print(ch)
<generator object <genexpr> at 0x7f2dab21ff90>
A
B
C

Reference

profile
graph data scientist

0개의 댓글