[Python] Generator (제너레이터)

손종일·2020년 8월 24일
0

Python

목록 보기
2/13
post-thumbnail

제너레이터 (Generator)

  • 제너레이터(Generator)는 이터레이터(iterator)를 생성해주는 함수입니다.
  • 이터레이터는 클래스에 __iter__, __next__ 또는 __getitem__ 메서드를 구현해야 하지만 제너레이터는 함수 안에서 yield라는 키워드만 사용하면 끝입니다.
  • 제너레이터는 이터레이터보다 훨씬 간단하게 작성할 수 있습니다.
  • 제너레이터는는 발생자라고 부르기도 한다.

제너레이터의 yield는 무엇인가?

함수 안에서 yield를 사용하면 함수는 제너레이터가 되며 yield에는 값(변수)을 지정합니다.
yield는 함수가 제너레이터를 반환한다는 것을 제외하고 return과 비슷하게 사용되는 키워드입니다.

제너레이터의 간단한 사용

def number_generator():
	yield 0
    	yield 1
    	yield 2
for i in number_generator():
	print(i)			# 0
					# 1
                    			# 2

제너레이터 객체가 이터레이터인지 확인하고 무슨 차이가 있는지 살펴보자.

  • num_generator 함수를 g에 할당하고 g를 호출해보면 제너레이터가 출력된다.
  • 또한, dir 함수로 메소드 항목을 확인해보면 iter와 next 메소드가 있는것을 확인할 수 있다.
  • 이터레이터는 __next__ 메소드 안에서 직접 return으로 값을 반환했지만, 제너레이터는 yield에 지정한 값이 __next__ 메소드의 반환값으로 나온다.
  • 이터레이터는 raise로 StopIteration 예외를 직접 발생시켰지만 제너레이터는 함수의 끝에 도달하면 자동으로 StopIteration 예외가 발생한다.
  • 제너레이터는 제너레이터 객체에서 __next__ 메소드를 호출할 때마다 함수 안의 yield까지 코드를 실행하며 yield에서 값을 발생시킨다.
def number_generator():
	yield 0		# 0을 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보
    	yield 1		# 1을 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보
    	yield 2		# 2을 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보
g = number_generator()
-
print(g)			
		# <generator object number_generator at 0x7fa66f973190>
print(dir(g))		
# ['__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__',
'__init_subclass__', '__iter__', '__le__', '__lt__', '__name__', '__ne__',
'__new__', '__next__', '__qualname__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw']
-
print(g.__next__())		# 0
print(g.__next__())		# 1
print(g.__next__())		# 2
print(g.__next__())		# StopIteration

제너레이터의 동작 과정

즉, return은 반환 즉시 함수가 끝나지만 yield는 잠시 함수 바깥의 코드가 실행되도록 양보하여 값을 가져가게 한 뒤 다시 제너레이터 안의 코드를 계속 실행하는 방식입니다.

def number_generator():
	yield 0		# 0을 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보
    	yield 1		# 1을 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보
    	yield 2		# 2을 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보
g = number_generator()
-
a = next(g)		#yield를 사용하여 함수 바깥으로 전달한 값은 next의 반환값으로 나온다.
b = next(g)
c = next(g)
print(a, b, c) 	# 0 1 2 

profile
Allday

0개의 댓글