본문 바로가기

프로그래머/Python

[널널한 교수의 고급 파이썬] 04-3 제너레이터와 yield(feat. return문)

04-3 제너레이터와 yield(feat. return문)

제너레이터 generator

  • 제너레이터 객체는 모든 값을 메모리에 올려두고 이용하는 것이 아니라 필요할 때마다 생성해서 반환하는 일을 한다
  • 이 때문에 메모리를 효율적으로 사용할 수 있다는 장점이 있다

제너레이터와 이를 이용한 for문

my_generator = (x for x in range(1,4))
for n in my_generator:
    print(n)

type(my_generator)
  • 반복자와 동일한 일을 하는 것처럼 보이지만 여기에서 생성된 1, 2, 3을 미리 메모리에 만들어 두는 것이 아니라 for문에서 필요할 때마다 my_generator로 부터 받아오며 메모리에서 보관하지 않는다는 점이다(lazy evaluation)

yield

  • 일반적인 함수의 return문과 유사하다
  • 하지만 yield문은 제너레이터를 반환한다는 점에서 return문과 차이가 있다
def create_gen():
    alist = range(1,4)
    for x in alist:
        yield x

my_generator = create_gen()
print(my_generator)

for n in my_generator:
    print(n) 

제너레이터를 사용할 때 주의사항

  • 제너레이터는 실행될 때 함수의 몸체를 실행하는 것이 아니라, 제너레이터 함수가 가진 객체를 반환하는 일을 한다
  • 제너레이터는 한 번 생성해서 반환한 객체를 보관하지 않기 때문에 이전의 코드를 실행한 후 추가한 코드를 실행하면 아무런 객체도 출력되지 않는다
def create_gen():
    alist = range(1,4)
    for x in alist:
        yield x

my_generator = create_gen()
print(my_generator)

for n in my_generator:
    print(n) 

for n in my_generator:  # 출력되지 않음
    print(n)

왜 제너레이터를 사용하나

  • 제너레이터는 메모리를 절약해준다
  • 제너레이터는 수행시간도 절약해준다

피보나치 수열 - 일반함수를 사용한 루프

import time

def fibon(n):
    a = b = 1
    result = []
    for i in range(n):
        result.append(a)
        a, b = b, a + b
    return resul

start_t = time.time()
print('total time = ', end_t - start_t)

피보나치 수열 - 제너레이터를 사용한 루프


import time
def fibon(n):
    a = b = 1
    for i in range(n):
        yield a
        a, b = b, a + b
    return resul

start_t = time.time()
print('total time = ', end_t - start_t)