[Python] 이터레이터(Iterator)와 제너레이터(Generator)

solved_err.log·2023년 3월 13일
0

파이썬에서 자주 접할 수 있는 용어인 이터레이터와 제너레이터에 대해 정리해보았다.

이터레이터(Iterator)

iterable한 객체를 내장 함수 또는 iterable객체의 메소드로 객체를 생성할 수 있다. 그렇다면 iterable한 객체란 무엇일까?
iterable, 반복 가능한 객체이다. 순서대로 다음 값을 리턴할 수 있는 객체를 의미하며, 파이썬에서 대표적으로 iterable한 타입은 list, dict, set, str, bytes, tuple, range 등이 있다.
예를 들어, list 객체는 다음과 같이 반복문을 통해 값을 사용할 수 있다. 이렇게 내부 요소를 하나씩 리턴할 수 있는 요소를 iterable한 객체라고 할 수 있다.

a = [1, 2, 3]

for item in a:
	print(item)

iter함수를 통해 iterable 객체를 iterator로 만들 수 있으며, iterator로 변경 후에 __next__() 함수 호출이 가능하다.

# 1. iter() 함수 사용 전
print(a.__next__) # AttributeError 발생


# 2. iter() 함수 사용 후
a = iter(a)
#a = [1, 2, 3].__iter__()	 # 같은 결과

print(a.__next__()) # 1 출력
print(a.__next__()) # 2 출력
print(a.__next__()) # 3 출력
print(a.__next__()) # StopIteration Exception

__next__() 함수를 호출해서 값을 반복적으로 꺼내 쓸 수 있고, 마지막 값까지 모두 꺼낸 후에는 StopIteration 예외가 발생한다.

제너레이터(Generator)

iterator를 생성해주는 함수이며, 함수안에 yield 키워드를 사용한다.
yield가 호출되면 암시적으로 return이 호출되며, 한번 더 실행되면 실행되었던 'yield' 다음 코드가 실행된다. 다음의 예제를 확인해보자.

def simple_gen():
    yield "Hello"
    yield "World"
    
gen = simple_gen()
print(gen)	 		# Hello 출력
print(next(gen))	# World 출력
print(next(gen))	# StopIteration Exception

처음 gen을 호출할 때에는 simple_gen()함수를 실행하다가 yield 키워드를 만나면서 "Hello" 값을 return하고 해당 위치를 기억한다.
이후, next함수를 통해 다시 함수가 호출되면 앞서 return한 이후부터 코드를 실행하고 yield 키워드를 만나면 또 다시 "World" 값을 return한다.

이렇게 생성한 genertaor는 iterable한 객체가 되며 for문에서 사용할 수 있게된다.

def list_generator():
	a = [1, 2, 3]
	for i in a:
		yield i		#한번씩 값을 바깥으로 전달

gen = list_generator()
#case 1.
print(list(gen))	# [1, 2, 3] 출력
#------------------------------

#case 2.
print(next(gen))	# 1 출력
print(next(gen))	# 2 출력
print(next(gen))	# 3 출력
#------------------------------

이와 같이, 제너레이터는 함수를 끝내지 않은 상태에서 yield를 사용해 값을 바깥으로 전달할 수 있다.
return은 반환 즉시 함수가 끝나지만 yield는 잠시 함수 바깥의 코드가 실행되도록 주도권을 양보하여 값을 가져가게 한 뒤 다시 제너레이터 안의 코드를 계속 실행하는 방식이다.

모든 제너레이터는 이터레이터에 포함된다고 할 수 있다.

profile
배우고 기록하는 개발 일기장✍

0개의 댓글