[Python] 제너레이터(Generator)

ITmakesmeSoft·2022년 10월 4일
0

PYTHON [ADVANCED]

목록 보기
1/2
post-thumbnail

Generator(제너레이터)?

  • 데이터를 미리 만들어 놓지 않고 필요할 때마다 즉석해서 하나씩 만들어낼 수 있는 객체
  • 모든 제너레이터(Generator)는 반복자(iterator)임
  • 호출을 할 수 있는 파라메터를 가지고 있으며, 연속적인 값을 생성
  • 한번에 모든 값을 포함한 배열을 만들어 리턴하는 대신에, yield 구문을 통해 한번 호출될 떄마다 하나의 값만을 리턴
  • 작은 메모리 사용량으로도 필요한 결과값을 낼 수 있음

일반 함수와 제너레이터의 차이점

일반적인 함수는 호출 시 모든 구문이 끝날 때까지 실행한 후, 모든 값을 리턴하고 종료되며, 종료 후에는 함수가 가지고 있던 모든 내부 함수나 로컬 변수는 메모리상에서 사라진다.

이 후 다시 같은 함수를 호출하면 모든 것이 처음부터 다시 새롭게 시작된다.

def square_numbers(nums):
    result = []
    for i in nums:
        result.append(i * i)
    return result

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

print(my_nums)   # [1, 4, 6, 16, 25]

하지만, 제너레이터의 경우 모든 결과값을 반환하거나 메모리에 저장하지 않고, 제너레이터라는 오브젝트를 반환함으로써, 나중에 호출될 때마다 하나의 값만을 전달(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 0x0000016B17E19EB0>

위와 같이 호출하더라도 제너레이터 오브젝트가 반환된다.

여기서 next()함수를 통해 값을 호출하면 제너레이터는 값을 하나만 반환한다.

print(next(my_nums)) # 1

여러번 반복하여 next()를 호출하면 다음과 같이 출력된다.

print(next(my_nums)) # 4
print(next(my_nums)) # 9
print(next(my_nums)) # 16
print(next(my_nums)) # 25

yield 키워드

파이썬에서는 yield키워드를 통해 기존의 함수와는 다른 방식으로 결과 값을 얻을 수 있다.

yield가 호출되면 암시적으로 return이 호출되며, 한 번 더 실행하면 실행되었던 yield의 다음 코드가 실행된다. 이렇게 yield를 이용하여 결과값을 나누어 얻으면 성능 측면에서 큰 이점이 있다.

return 키워드를 사용할 경우 모든 결과값을 메모리에 올려놓아야 하는 반면, yield 키워드를 이용한 경우 결과 값 하나 씩만을 메모리에 올려둔다. 한정된 리소스를 효율적으로 활용해야 하는 경우 제너레이터를 이용하면 도움이 된다.


yield from

제너레이터를 반환하는 함수를 작성할 때, yield from 키워드를 사용하면 반복문 없이도 리스트를 제너레이터로 변환할 수 있다.

# 1. 반복문 사용
def generator():
	for char in ['A,'B','C']:
		yield char

# 2. yield from 사용
def generator():
	yield from ['A,'B','C']

Generator Comprehension

yield 키워드를 이용하지 않고 제너레이터 표현식을 통해서도 제너레이터를 만들 수도 있다.

방법은 리스트 컴프리핸션과 비슷하다. 차이점은 리스트 컴프리핸션은 대괄호를 사용하고, 제너레이터 컴프리핸션은 소괄호를 사용한다는 점이다.

lst1 = [x for x in range(5)] # 리스트 컴프리핸션
lst2 = (x for x in range(5)) # 제너레이터 컴프리핸션

print(lst1) # [0, 1, 2, 3, 4]
print(lst2) # <generator object <genexpr> at 0x00000227CC3259E0>

for x in lst2:
	print(x, end = ' ') # 0 1 2 3 4

Reference

- 파이썬의 yield 키워드와 제너레이터(generator)
- 파이썬 - 제너레이터 (Generator) - schoolofweb.net
- 점프 투 파이썬

profile
💎 Daniel LEE | SSAFY 8th

0개의 댓글