TIL (2020.06.01)

Awesome·2020년 6월 1일
0

TIL

목록 보기
8/46

Python

Generator - Lazy Evaluation

어제 했던 generator 와 관련하여 list-comprehension vs generator-expression 에 대해 다뤄보겠다.

우선, generator는 iterator를 생성하는 함수이다. __iter__,__next__ method 없이도 반복 가능한 generator 객체를 생성할 수 있다.

Generator를 만드는 방식 중에서 특히, generator-expression 이 있다. 앞선 list 표현식과 같은 방법이지만 괄호의 차이로 나뉜다.
코드 뿐만 아니라 성능에서도 차이가 난다. 그 이유는 lazy evaluation 때문이다.

Lazy Evaluation : 어떤 값이 사용되기 전까지 코드 진행을 뒤로 미루는 방식

import time

L = range(5)

def print_iter(iter):
    counter = 1
    for element in iter:
        print(element)
        counter -= 1
        if counter == 0:
            break

def lazy_return(num):
    print("sleep 1s")
    time.sleep(1)
    return num

print("comprehension_list=")  # 리스트 표현식
comprehension_list = [ lazy_return(i) for i in L ]
print_iter(comprehension_list)

print("generator_exp=")       # 제너레이터 표현식
generator_exp = ( lazy_return(i) for i in L )
print_iter(generator_exp)

위와 같은 예제가 있다.
우선 0부터 4까지의 범위를 갖는 range를 변수 L에 선언하였다. print_ iter 함수는 iterator 를 인자로 받아 반복한다. 다만 counter라는 변수를 1로 지정한 이유는 단 한번만 실행하기 위함이다.
List-comprehension과 generator-expression 을 비교하기 위하여 각각의 실행문을 작성하였다. 표현식 안에서 lazy_return 이라는 함수를 사용하여 0~4 까지의 값을 매 시도마다 1초씩 시간 간격을 주고 생성한다.
각각의 결과는 아래와 같다.

> comprehension_list=
> sleep 1s
> sleep 1s
> sleep 1s
> sleep 1s
> sleep 1s
> 0
> generator_exp=
> sleep 1s
> 0

결과를 보면, list-comprehension의 경우 5회가 실시되었다. 리스트는 반복문이 실행됨과 동시에 모든 결과값을 생성하여 저장하기 때문이다. 따라서 자연스럽게 시간 간격도 1초씩 총 5초가 적용되었다.
하지만 generator-expression 같은 경우에는 단 1회 실행되었다. time.sleep도 1회 밖에 적용받지 않았다. lazy evaluation 으로 인한 차이가 여기서 발생한다.

앞서 정의했듯이, lazy evaluation 은 계산을 바로 실행하지 않고 그 값이 사용(호출)되기 전까지 생성하지 않는다. 오로지 generator만 존재할 뿐이다. print_iter 함수에서 1회 출력 뒤, counter 변수가 0이 되므로 해당 함수는 종료한다. 따라서 generator 에서 첫 번째 값인 0만 출력되는 것이다.

굳이 계산해보지 않아도 4초 이상의 시간적인 효율이 발생한다. 데이터가 커질수록 메모리와 시간적인 효율성은 더 커질 것이라고 자연스럽게 추측 가능하다.
그래도 직접 메모리 확인을 해보자.

import sys
print("comprehension_list size:",sys.getsizeof(comprehension_list))
print("generator_exp size:",sys.getsizeof(generator_exp))

# bytes 단위
> comprehension_list size: 120
> generator_exp size: 112

속도는 물론 메모리에서도 lazy evaluation 방식의 generator-expression 이 list-comprehension 보다 효율적임을 확인할 수 있다.

profile
keep calm and carry on

0개의 댓글