Generator

Nam Eun-Ji·2020년 11월 14일
0

python-비동기

목록 보기
2/4
  • iterator를 생성해주는 함수
  • 함수 안에 yield 키워드를 사용한다.
  • iterable한 순서가 지정됨(모든 generator는 iterator)
  • 느슨하게 평가된다.(순서의 다음 값은 필요에 따라 계산됨)
  • 함수의 내부 로컬 변수를 통해 내부상태가 유지된다.


yield

일반적인 함수의 경우 사용이 종료되면 결과값을 호출부로 반환 후 함수 자체를 종료시킨 후 메모리 상에서 클리어 된다. 하지만 generator 함수가 실행 중 yield 를 만날 경우, 해당 함수는 그 상태로 정지 되며, 반환 값을 next() 를 호출한 쪽으로 전달 하게 된다. 이후 해당 함수는 일반적인 경우 처럼 종료되는 것이 아니라 그 상태로 유지되게 된다. 즉, 함수에서 사용된 local 변수나 instruction pointer 등과 같은 함수 내부에서 사용된 데이터들이 메모리에 그대로 유지되는 것이다.

def generator(n):
    i = 0
    while i < n:
        yield i
        i += 1

for x in generator(5):
	print(x)

0
1
2
3
4 

yield from

파이썬 3.3 이상 부터 사용가능

def generator():
	a = [1, 2, 3]
	for i in a:
		yield i

gen = generator()
list(gen)  # [1, 2, 3]

위와 같이 iterable한 객체를 yield할 때에는 아래와 같이 for문 대신 yield from으로 값을 전달할 수 있다.

def generator():
	a = [1, 2, 3]
	yield from a

gen = generator()
list(gen)  # [1, 2, 3]


generator expression

()를 사용하면 generator object로 생성된다.

>>> [ i for i in xrange(10) if i % 2 ]
[1, 3, 5, 7, 9]

>>> ( i for i in xrange(10) if i % 2 )
<generator object <genexpr> at 0x7f6105d90960>


generator를 왜 사용하는가?

memory를 효율적으로 사용할 수 있다.

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

import sys

a = [i for i in range(1000)]  # <class 'list'>
b = (i for i in range(1000))  # <class 'generator'>

sys.getsizeof(a)  # 9016
sys.getsizeof(b)  # 112

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

이러한 Generator는 데이타가 무제한이어서 모든 데이타를 리턴할 수 없는 경우나, 데이타가 대량이어서 일부씩 처리하는 것이 필요한 경우, 혹은 모든 데이타를 미리 계산하면 속도가 느려서 그때 그때 On Demand로 처리하는 것이 좋은 경우 등에 종종 사용된다.




출처
https://wikidocs.net/16069
https://bluese05.tistory.com/56

profile
한 줄 소개가 자연스러워지는 그날까지

0개의 댓글