이터레이터는 값을 순차적으로 꺼내올 수 있는 객체입니다.
iterator는 iterable한 객체를 내장함수 또는 iterable객체의 메소드로 객체를 생성할 수 있습니다.
파이썬 내장함수 iter()를 사용해 iterator 객체를 생성 할 수 있습니다.
Iterator는 iter 함수의 인자로 Iterable을 적용해 반환된 객체로, 값을 하나씩 반환하며 그 상태값을 유지, 관리하는 객체의 개념입니다.
terator는 Iterable에 iter 내장 함수를 적용해 반환되는 객체로서 next 함수를 통해 값을 한 번에 한 번씩 반환하는 특징이 있습니다. 내부적으로 현재까지의 반환 상태를 관리하고 조건에서 정의한 마지막까지 반환하면 더 사용할 수 없으며 StopIteration 예외 발생시킵니다.
Lazy Evaluation은 어떤 값이 실제로 쓰일 때 까지 그 값의 계산을 뒤로 미루는 동작 방식입니다.
밑에 코드 예제를 통해 알아보겠습니다.
import time
def print_iter(iter):
for element in iter:
print(element)
def lazy_return(num):
print("sleep 1s")
time.sleep(1)
return num
print("comprehension_list=")
comprehension_list = [ lazy_return(i) for i in L ]
print_iter(comprehension_list)
print("generator_exp=")
generator_exp = ( lazy_return(i) for i in L )
print_iter(generator_exp)
해당 코드를 실행시켜보면
print_iter(comprehension_list)
1
2
3
print_iter(generator_exp)
sleep 1s
1
sleep 1s
2
sleep 1s
3
이러한 결과를 확인할 수 있습니다. 프린트 결과를 떠나 어떤 방식으로 작동이 되는지가 중요합니다.
list 같은 자료구조는 내부 데이터의 크기에 따라 총 크기가 결정되므로 저렇게 큰 크기의 list를 선언하면, 일반 컴퓨터의 한정된 용량의 메모리로는 감당할 수 없기 때문입니다.
그에 반해 iterator, generator 일련의 값을 사용할 때 모든 데이터를 메모리에 모두 로딩하는 대신 한 값씩 필요할 때마다 로딩, 평가함으로써(lazy loading, evaluate) 메모리를 절약하고, 메모리 부족으로 프로그램이 실패하는 것을 방지할 수 있다는 점이 다릅니다.
매우 큰 파일을 읽는다거나, 네트워크를 통해 대용량의 데이터를 다운로드할 때를 생각해보면, 줄 등의 한 단위를 필요할 때 한 줄씩 평가하는(evaluate) lazy loading이 한 번에 모든 데이터를 loading하는 방식보다 안전한 것입니다. 따라서 상황에 맞게 사용하는 것이 필요할 것 같습니다.
출처 : https://shoark7.github.io/programming/python/iterable-iterator-generator-in-python