Python

[Python] 이터러블 객체

UnoCoding 2023. 2. 1. 21:08

이터러블 객체란?

 

파이썬에는 기본적으로 반복 가능한 객체가 있습니다. 예를들어 list, tuple, set, dict 이것 들은 다 for문을 돌릴 수 있다는 특징이 있습니다.

 

그러나 이러한 for문은 위 객체에만 돌릴수 있는 것은 아닙니다.

__iter__ or __next__ 매직 매소드가 구현이 되어 있느지를 통해 이터레이터를 판단할 수 있다.

또한 객체가 시퀀스이고 __lne__과 __getitem__을 모두 가졌는지 여부에 따라 for문에서 사용할 수 있는 객체를 만들수 있다.

 

이러터블 객체 만들기

 

일정 기간의 날짜를 하루 간격으로 반복하는 객체의 코드를 예시로 이해보겠습니다. 중요한 것은 __iter__, __next__ 매직 메서드를 중점으로 보자.

from datetime import timedelta, date


class DateRangeIterable:
    """Iterable class for date range"""

    def __init__(self, start, end):
        self.start = start
        self.end = end
        self._present = start

    def __iter__(self):
        return self

    def __next__(self):
        if self._present > self.end:
            raise StopIteration

        today = self._present
        self._present += timedelta(days=1)
        return today


for day in DateRangeIterable(date(2019, 1, 1), date(2019, 1, 5)):
    print(day)

Output

2019-01-01
2019-01-02
2019-01-03
2019-01-04
2019-01-05

 

시퀀스 만들기

 

모든 시퀀스는 순서가 유지되고, 정수로 인덱싱하며, 길이가 있다.

 

예를 들자면 다음과 같은 3가지 자료구조가 존재한다.

  • 문자열: 'Hello'. 문자열(string)은 문자(character)들의 시퀀스다.
  • 리스트: [1, 4, 5].
  • 튜플: ('GOOG', 100, 490.1).

여기서 필요한 매직 메서드는 __getitem__, __len__ 이다. 

class DateRangeSequence:
    """Sequence class for date range"""

    def __init__(self, start, end):
        self.start = start
        self.end = end
        self._range = self._create_range()

    def _create_range(self):
        days = []
        current_day = self.start
        while current_day <= self.end:
            days.append(current_day)
            current_day += timedelta(days=1)
        return days

    def __getitem__(self, item):
        return self._range[item]

    def __len__(self):
        return len(self._range)


s1 = DateRangeSequence(date(2019, 1, 1), date(2019, 1, 5))
for day in s1:
    print(day)

위 이터러블 예제를 시퀀스로 구현한 형태이다.

 

그럼 대체 언제 시퀀스로 써야하고 언제 이터너블로 써야 할까?

 

이터러블 객체는 메모리를 적게 사용한다는 장점이 있다. 즉 한 번에 하나의 날짜만  보관하고 한 번에 하나씩 날짜를 생성한다. 그러나 이는 n번째 요소를 얻기 위해 n까지 도달하려고 n번 반복실행(O(n))한다. 이 문제는 전형적인 CPU와 메모리의 트레이드오프이다.

 

시퀀스로 구현을 하면 오히여 이터러블 보다 메모리를 더 많이 사용한다(모든 결과값을 가지고 있음) 하지만 특정 요소를 가져오는데 필요한 시간복잡도는 O(1)로 찾을 수 있다.

 

두가지 구현 중 어느 것을 사용할지 결정할 때 메모리와 CPU 사이의 트레이드오프를 계산해 보자,

일반적으로 이터레션이 더 좋은 선택이자만 모든 경우의 요건을 염두해야 한다.