[Python] 제너레이터(Generator)

강동연·2021년 12월 30일

[Python]

목록 보기
1/3

👌 기본적으로 AIFFEL FUNDIMENTALS 자료를 참고했습니다.

Generator란??

  • In Python Wiki
    "Generator functions allow you to declare a function that behaves like an iterator, i.e. it can be used in a for loop."

간략하게 요약하자면..

  • Generator: iterator를 생성해 주는 함수
  • iterator: next()를 메서드를 이용해 데이터에 순차적으로 접근이 가능한 객체

간단한 Generator 예시

출처: https://bluese05.tistory.com/56

def generator(n):
    i = 0
    while i < n:
        yield i
        i += 1
        
for x in generator(5):
	print x
    
>>>
0
1
2
3
4

🤟 코드 설명
1. for 문이 실행되며, 먼저 generator 함수가 호출된다.
2. 실행 중 while 문 안에서 yield 를 만나게 된다. 그러면 return 과 비슷하게 함수를 호출했던 구문으로 반환하게 된다. 여기서는 첫번재 i 값인 0 을 반환하게 된다. 하지만 반환 하였다고 generator 함수가 종료되는 것이 아니라 그대로 유지한 상태이다.
3. x 값에는 yield 에서 전달 된 0 값이 저장된 후 print 된다. 그 후 for 문에 의해 다시 generator 함수가 호출된다.
4. 이때는 generator 함수가 처음부터 시작되는게 아니라 yield 이후 구문부터 시작되게 된다. 따라서 i += 1 구문이 실행되고 i 값은 1로 증가한다.
5. 아직 while 문 내부이기 때문에 yield 구문을 만나 i 값인 1이 전달 된다.
6. x 값은 1을 전달 받고 print 된다. (이후 반복)

위 티스토리 코드 설명이 너무 깔끔하고 이해하기 쉬워 가지고 왔습니다!!

단순 For문과 Generator 비교

  • 단순 For문
   my_list = ['a','b','c','d']

    # 인자로 받은 리스트를 가공해서 만든 데이터셋 리스트를 리턴하는 함수
    def get_dataset_list(my_list):
        result_list = []
        for i in range(2):
            for j in my_list:
                result_list.append((i, j))
                print('>>  {} data loaded..'.format(len(result_list)))
        return result_list

    for X, y in get_dataset_list(my_list):
        print(X, y)
   
>>>
>>  1 data loaded..
>>  2 data loaded..
>>  3 data loaded..
>>  4 data loaded..
>>  5 data loaded..
>>  6 data loaded..
>>  7 data loaded..
>>  8 data loaded..
0 a
0 b
0 c
0 d
1 a
1 b
1 c
1 d
  • Generator
   
my_list = ['a','b','c','d']

# 인자로 받은 리스트로부터 데이터를 하나씩 가져오는 제너레이터를 리턴하는 함수
def get_dataset_generator(my_list):
    result_list = []
    for i in range(2):
        for j in my_list:
            yield (i, j)   # 이 줄이 이전의 append 코드를 대체했습니다
            print('>>  1 data loaded..')

dataset_generator = get_dataset_generator(my_list)
for X, y in dataset_generator:
    print(X, y)   

>>>
0 a
>>  1 data loaded..
0 b
>>  1 data loaded..
0 c
>>  1 data loaded..
0 d
>>  1 data loaded..
1 a
>>  1 data loaded..
1 b
>>  1 data loaded..
1 c
>>  1 data loaded..
1 d
>>  1 data loaded..  

위 두 코드의 차이를 아시겠나요?? 코드결과를 보면 단순For문은 get_dataset_list() 함수 안의 로직을 전부 실행난 다음 Return 한 result_list를 실행시킵니다. 하지만 Generator는 get_dataset_generator() 전부 실행시키는 것이 아닌 yield 지점에서 멈춘 후 실행되는 것을 볼 수 있습니다.

그렇다면 Why Generator??

  • Generator의 장점???

    1. memory를 효율적으로 사용할 수 있다.
    2. Lazy evaluation(계산 값이 필요할때 까지 계산을 늦추는 효과)

    1. Memory의 효율성

import sys

sys.getsizeof( [i for i in xrange(100) if i % 2] )    # list

>> 536

sys.getsizeof( [i for i in xrange(1000) if i % 2] )

>> 4280

sys.getsizeof( (i for i in xrange(100) if i % 2) )    # generator

>> 80

sys.getsizeof( (i for i in xrange(1000) if i % 2) )

>> 80

위의 코드결과를 보면 Generator의 경우 list의 사이즈와 상관없이 사이즈가 일정한 것을 볼 수 있다. (참고로 [i for i in xrange(100) if i % 2]는 list comprehension이고 (i for i in xrange(100) if i % 2)는 generator comprehension 이다.)

"list 는 list 안에 속한 모든 데이터를 메모리에 적재하기 때문에 list의 크기 만큼 차지하는 메모리 사이즈가 늘어나게 된다. 하지만 generator 의 경우 데이터 값을 한꺼번에 메모리에 적재 하는 것이 아니라 next() 메소드를 통해 차례로 값에 접근할 때마다 메모리에 적재하는 방식이다."

2. Lazy evlaution

Lazy evaluation 즉 계산 결과 값이 필요할 때까지 계산을 늦추는 효과를 볼 수 있다.

단순 For문과 Generator 비교 의 Lazy evaluation의 예시.

✔ 정리..

마지막으로 정리하자면 가장 중요한점은 Generator를 사용하면 메모리를 최대한 효율적으로 사용할 수 있다는 짐이라고 생각한다. 대용량의 데이터를 사용할 수록 Generator를 사용해야 한다는 생각이 든다....



[참고 자료]

- 저작권 문제가 있을 시 해당 게시물을 즉각 수정 및 삭제 조치하겠습니다.

profile
Maybe I will be an AI Engineer?

0개의 댓글