Iterator, Generator
참고
Iterable
iterable 객체는 내부 요소를 하나씩 리턴 할 수 있음
즉, for 문을 통해 순회 할 수 있는 객체를 iterable!
for item in iterable:
pass
대표적으로 list, tuple, set, dictionary, strting, bytes, range 등이 존재
객체가 iterable한지 알아보고 싶으면 collections.Iterable
에 속한 instance인지 확인
import collections
lst = [1, 2, 3, 4]
isinstance(lst, collections.Iterable)
Iterator
Iterator는 복수의 데이터가 들어있는 컨테이터 (list, tuple, set, dictionary, strting) 에서 값을 차례대로 꺼낼 수 있는 객체 (Object)
데이터가 너무 많은 경우 미리 만들어두는 것보다 필요할 때마다 값을 뽑아 사용하는 경우가 대부분의 경우에서 효율적이기 때문에 사용
하지만 반복이 가능한, 즉 iterable한 객체에서만 사용이 가능
iter()
로 iterable한 객체로 변환 할 수 있고 변환된 객체는 next()
로 다음 값 뽑아 사용 가능
한 번 반복을 다 하면, 즉 다음에 뽑을 것이 없으면 다시 사용할 수 없다는 특징이 있음
Python 예제
lst = [1, 2, 3, 4]
print(lst.__iter__)
print(lst.__next__)
<method-wrapper '__iter__' of list object at 0x766700a98180>
...
AttributeError: 'list' object has no attribute '__next__'
이와 같이 list는 iterable한 객체 이지만 iteration한 객체는 아님을 확인
iterator_lst = iter(lst)
print(type(iterator_lst))
print(iterator_lst.__iter__)
print(iterator_lst.__next__)
<class 'list_iterator'>
<method-wrapper '__iter__' of list_iterator object at 0x766701a3f4c0>
<method-wrapper '__next__' of list_iterator object at 0x766701a3f4c0>
iter()
내장 함수를 통해 iteration 객체로 변환시키면 type이 바뀌는 것을 확인 할 수 있고__next__
매직 매소드를 가지게 된 것을 확인
print(next(iterator_lst))
print(next(iterator_lst))
print(next(iterator_lst))
print(next(iterator_lst))
print(next(iterator_lst))
1
2
3
4
....
StopIteration:
next()
를 통해 값을 확인해보면 순차적으로 값이 나오다가 나올 값이 없으면 에러 발생
Generator
Generator는 iterator를 생성해주는 함수
즉, generator는 특이한 iterator라고 볼 수 있음 (반대는 성립하지 않음)
보통 다음 값을 필요에 따라 계산이 되고 함수 내부 로컬 변수를 통해 내부 상태가 유지됨
함수가 하나의 고정된 값을 반환하는 것이 아니라 순차적으로 다른 값을 반환해야할 때 사용하거나 상황마다 다른 값을 return 해야 할 때, return 하는 시점을 다르게 하고 싶을 때 사용
Generator는 yield()
을 이용하여 생성할 수 있으며 흔하게 알고 있는 list comprehension 등의 표현식도 generator
yield()
가 호출이되면 암시적으로 return이 호출되고, 한 번 더 실행되면 yield()
다음 코드 실행
Python 예제
def generator():
yield 'a'
yield 'b'
yield 'c'
g = generator()
type(g)
generator
yield
를 사용하면 generator type이 되는 것을 확인
print(next(g))
print(next(g))
print(next(g))
print(next(g))
a
b
c
...
StopIteration:
generator 역시 순차적으로 값이 나오다가 나올 값이 없으면 에러가 발생함
가게에서 웨이팅 하는 손님에게 몇 번째 웨이팅 손님 입장하라고 알려주는 코드를 작성할 때도 쓸 수 있음
def waiting_count(max_count):
cnt = 1
for num in range(max_count):
print(f'{cnt} 번 손님 입장 가능')
cnt += 1
yield
generator = waiting_count(10)
next(generator)
next(generator)
1 번 손님 입장 가능
2 번 손님 입장 가능
Generator를 이용하여 코드를 작성하면 시점에 맞게 실행할 수 있음
즉, 입장이 가능해져 이 message를 전송하려고 할 때 보낼 수 있음