Python

[Python] Iterable 객체 생성 - 이터레이터 & 제너레이터

Hyper_ 2024. 2. 29. 16:47

파이썬 이터레이터와 제너레이터는 'Iterable'한 객체입니다.

파이썬의 'Iterable'이라는 개념을 염두에 두고 두 개념을 각각 살펴보겠습니다.


1. 이터레이터(Iterator)

  • 'iterable'한 객체이며 next() 함수 호출 시 지니고 있는 요소를 순차적으로 반환하는 객체
  • 'iterable'한 객체이기에 for문과 함께 사용이 가능
  • iter() 내장함수를 통해 리스트, 세트, 튜플 등 iterable한 객체를 이터레이터 객체로 변환 가능
  • 이터레이터 객체는 지니고 있는 요소를 각 한 번씩만 반환합니다.
# 이터레이터 객체에 대한 이해
>>> a = [1, 2, 3]
>>> ia = iter(a)
>>> type(ia)
<class 'list_iterator'>
>>> next(ia)
1
>>> next(ia)
2
>>> next(ia)
3



# 이터레이터 객체와 for 반복문
>>> for i in ia:
        print(i)
1
2
3

 

 

  • 이터레이터는 '__iter__()'메서드로 자신을 (객체로써)반환하고, '__next__()' 메서드로 다음 요소를 반환
# 이터레이터 객체 구현(클래스)

class MyItertor:
    def __init__(self, data):
        self.data = data
        self.position = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.position >= len(self.data):
            raise StopIteration
        result = self.data[self.position]
        self.position += 1
        return result

 

 

 

 

2. 제너레이터(Generatior)

  • 이터레이터를 클래스가 아닌 '함수'로 간단하게 구현한 객체
  • 함수 내 yield 키워드가 사용되면 제너레이터가 된다!
  • 'gen = my_generator()'와 같이 이터레이터 객체 생성과 표면적으론 같은 방식으로 제너레이터 객체 생성
  • 이터레이터와 마찬가지로, 'iterable'한 객체이다.
  • 제너레이터 또한 지니고 있는 요소를 각 한 번씩만 반환합니다.
  • 제너레이터는 필요할 때만 값을 생성(lazy evalutation)하기 때문에 메모리 효율성이 높고, 대용량 데이터를 처리하는데 유리하다.
# 제너레이터 구현
def my_generator():
    yield 1
    yield 2
    yield 3


# 제너레이터 객체 생성
gen = my_generator()
print(next(gen))  # 1
print(next(gen))  # 2
print(next(gen))  # 3
# 다음 next(gen) 호출 시 StopIteration 예외 발생


# 제너레이터와 for문
gen2 = my_generator()
for i in gen2:
    print(i)
1
2
3

 

2-1. 'yield'의 작동방식

  • 값 반환: 'yield' 키워드 다음에 오는 표현식의 값을 호출자에게 반환. 이 때 함수의 실행은 'yield' 위치에서 일시중지
  • 함수 실행의 일시중지와 재개: 'yield'를 만날 때마다 함수는 해당 상태(지역 변수, 실행 위치 등)를 보존하고 일시 중지됩니다. next()함수를 통해 호출되면, 함수는 'yield' 다음부터 실행을 재개합니다.
  • 제너레이터의 종료: 함수 본문의 끝에 도달하거나, 'return'문을 만나면, 제너레이터는 'StopIteration' 예외를 발생시켜 반복이 종료되었음을 알립니다.

 

2-2. 제너레이터 표현식

  • 제너레이터를 간결하고 효율적으로 생성하는 방식(문법)
  • 간단하고 짧은 방식으로 간결성메모리 효율성 두 마리 토끼를 모두 챙길 수 있음
  • def(사용자함수 정의)와 'yield'를 이용한 제너레이터 정의가 아닌, 리스트 컴프리헨션과 유사한 문법과 소괄호'()'를 이용한 제너레이터 생성법
  • 제너레이터 표현식 또한 필요할 때만 값을 하나씩 생성하고, 모든 값을 한 번에 메모리에 로딩하지 않기 때문에 대용량 데이터를 처리할 때, 메모리 사용을 최소화 할 수 있다!
# 제너레이터 표현식 기본 문법
(expression for item in iterable if condition)

 

  • expression: 각 item에 대해 적용하여 요소를 만드는 표현식
  • item : 'iterable'로부터 순차적으로 반환되는 각 요소들을 담는 변수
  • 'iterable': 반복가능한 객체. 가지고 있는 요소를 하나씩 반환
  • condition: (선택사항) 이 조건이 True인 경우의 'iterable'요소만 item으로 반환 됨

 

 

 

 

3. 이터레이터와 제너레이터의 주요 차이점

  • 구현 방법: 이터레이터는 클래스로 정의하여 객체에 할당. 제너레이터는 함수로 생성.
  • 구현 핵심: 이터레이터는 'class'와 '__iter__()', '__next__()'로 구현, 제너레이터는 'def'와 'yield'로 구현
  • 메모리 효율성: 제너레이터는 값이 필요할 때만 생성되므로, 큰 데이터 시퀀스를 다룰 때 메모리 절약 가능