TIL 5. Generators

jiffydev·2020년 9월 18일
0

Generators

1. 정의

제너레이터는 반복문의 반복을 통제하기 위해 사용하는 루틴/함수이다. 모든 제너레이터는 이터레이터 이기도 하다. 제너레이터에는 매개변수가 존재하고 호출될수 있으며, 연속적인 값을 생성하므로 배열을 리턴하는 함수와도 유사한 면이 있다. 하지만 일반적인 배열을 생성할 때는 모든 값을 포함하고 한번에 리턴하는 반면, 제너레이터는 값을 한번에 하나씩 생성(yield)한다. 그러므로 메모리를 적게 사용할 뿐만아니라 호출자가 초반 몇개의 값을 즉시 처리할 수 있게 한다. 즉, 제너레이터는 함수처럼 생겼지만 이터레이터처럼 행동한다. 출처

def square_numbers(nums):
    for i in nums:
        yield i * i

my_nums = square_numbers([1, 2, 3, 4, 5])  #1

print my_nums

>> <generator object square_numbers at 0x1007c8f50>

제너레이터가 값을 yield할 때는 메모리에 저장하지 않기 때문에 함수를 실행해도 값이 출력되지는 않는다. 따라서 값을 출력하기 위해서는 next()함수를 통해 하나씩 호출하거나 반복문으로 출력해야 한다. 제너레이터는 특이하게도 yield시 상태를 저장하기 때문에(일반적인 함수는 리턴하면 함수는 끝난다) 값을 생성하고도 종료하지 않고 다음 값을 출력해줄 수 있다. 다만 next()함수를 사용할 경우 값의 개수 이상으로 사용하면 StopIteration예외가 발생한다.

2. Generator Expressions

리스트에 List Comprehension이 있는 것처럼 제너레이터에도 같은 기능이 존재한다.


my_nums = (x*x for x in [1, 2, 3, 4, 5])  

print my_nums

for num in my_nums:
    print num
 
 >>
 <generator object <genexpr> at 0x1007c8f50>
1
4
9
16
25

위와 같이 제너레이터를 생성할 수 있다. list comprehension과의 차이는 제너레이터는 값을 요청받았을 때만 불러온다는 것과, 한번만 반복한다는 것 등이 있다. 또한 예에서는 크기가 작았지만, 만약 대용량의 데이터를 리스트로 만들 경우 모든 값을 저장하기 때문에 제너레이터에 비해 훨씬 긴 시간이 걸린다.

3. 특징

  • 값을 메모리에 저장하지 않기 때문에 인덱싱이 불가능하다.
  • Lazy Evaluation: 함수를 실행할 때 인자를 넘기는 순서나 어떤 값을 함수에게 전달할지를 평가하는 것을 evaluation strategy 라고 한다. 여러 종류의 전략 중 lazy evaluation은 최소한의 평가를 하는 경향이 있는데, 값이 필요할 때까지는 평가를 미루는 전략이다. 평가를 최소한으로 하기 때문에 중복된 평가를 줄일 수 있고, 그로 인해 메모리 사용이 적다.
profile
잘 & 열심히 살고싶은 개발자

0개의 댓글