파이썬에서는 반복(iteration)이라는 개념이 매우 중요하며, 이터레이터(Iterator)와 이터러블(Iterable)은 이를 구현하는 핵심 개념입니다. 이 두 개념을 이해하면 파이썬의 반복 구조를 더욱 효율적으로 활용할 수 있습니다. 이번 글에서는 이터레이터와 이터러블의 개념, 차이점, 그리고 이를 활용하는 방법에 대해 알아보겠습니다.

1. 이터러블(Iterable)이란?

이터러블(Iterable)은 반복할 수 있는 객체를 의미합니다. 파이썬에서 리스트, 튜플, 문자열, 딕셔너리, 세트와 같은 객체들은 모두 이터러블입니다. 이터러블 객체는 for 루프와 함께 사용할 수 있으며, __iter__() 메서드를 구현하여 이터레이터 객체를 반환할 수 있습니다.

1.1. 이터러블의 예시

# 리스트는 이터러블 객체입니다.
my_list = [1, 2, 3, 4, 5]

# for 루프를 사용하여 반복할 수 있습니다.
for item in my_list:
    print(item)

위 코드에서 my_list는 이터러블 객체이며, for 루프를 통해 요소를 반복할 수 있습니다.

1.2. iter() 함수

이터러블 객체는 iter() 함수를 통해 이터레이터를 반환할 수 있습니다.

my_list = [1, 2, 3]
iterator = iter(my_list)

print(iterator)  # 출력: <list_iterator object at 0x...>

iter() 함수는 이터러블 객체의 __iter__() 메서드를 호출하여 이터레이터 객체를 반환합니다.

2. 이터레이터(Iterator)란?

이터레이터(Iterator)는 이터러블 객체의 요소를 하나씩 순차적으로 반환하는 객체입니다. 이터레이터는 __next__() 메서드를 구현하여 다음 요소를 반환하며, 요소가 더 이상 없을 경우 StopIteration 예외를 발생시킵니다. 이터레이터는 한 번 반복을 시작하면 다시 처음으로 돌아갈 수 없습니다.

2.1. 이터레이터의 예시

my_list = [1, 2, 3]
iterator = iter(my_list)

print(next(iterator))  # 출력: 1
print(next(iterator))  # 출력: 2
print(next(iterator))  # 출력: 3
print(next(iterator))  # StopIteration 예외 발생

위 코드에서 next() 함수는 이터레이터의 __next__() 메서드를 호출하여 다음 요소를 반환합니다. 더 이상 반환할 요소가 없으면 StopIteration 예외가 발생합니다.

3. 이터러블과 이터레이터의 차이

  • 이터러블(Iterable): 반복 가능한 객체로, __iter__() 메서드를 구현하여 이터레이터를 반환할 수 있습니다. 예를 들어, 리스트, 튜플, 문자열 등이 이터러블입니다.
  • 이터레이터(Iterator): 이터러블 객체에서 __iter__() 메서드를 통해 반환되는 객체로, __next__() 메서드를 통해 요소를 순차적으로 반환합니다.

이터러블 객체는 for 루프와 같은 반복문에서 사용할 수 있으며, 이터레이터는 이터러블의 요소를 하나씩 반환합니다.

3.1. 이터러블과 이터레이터를 활용한 반복

my_list = [1, 2, 3]
iterator = iter(my_list)

while True:
    try:
        item = next(iterator)
        print(item)
    except StopIteration:
        break

위 코드는 for 루프를 사용하는 대신, while 루프와 이터레이터를 사용하여 반복을 수행하는 방법을 보여줍니다.

4. 커스텀 이터러블과 이터레이터 구현

파이썬에서는 사용자가 직접 이터러블과 이터레이터를 정의할 수 있습니다. 이를 통해 특정 요구사항에 맞는 반복 동작을 구현할 수 있습니다.

4.1. 커스텀 이터러블 클래스 구현

class MyIterable:
    def __init__(self, data):
        self.data = data

    def __iter__(self):
        return MyIterator(self.data)

class MyIterator:
    def __init__(self, data):
        self.data = data
        self.index = 0

    def __next__(self):
        if self.index < len(self.data):
            item = self.data[self.index]
            self.index += 1
            return item
        else:
            raise StopIteration

# 사용 예시
my_iterable = MyIterable([1, 2, 3, 4, 5])
for item in my_iterable:
    print(item)

위 코드는 MyIterable이라는 커스텀 이터러블 클래스를 정의하고, 그에 대한 이터레이터 MyIterator를 구현한 예제입니다. 이 예제에서는 리스트의 요소를 순차적으로 반환하는 커스텀 반복을 정의했습니다.

5. 이터레이터의 장점과 활용

5.1. 메모리 효율성

이터레이터는 한 번에 하나의 요소만 메모리에 로드하므로, 매우 큰 데이터셋을 처리할 때 메모리 효율성이 뛰어납니다. 이터레이터를 사용하면 메모리에 전체 데이터를 로드하지 않고도 데이터를 처리할 수 있습니다.

5.2. 지연 평가(Lazy Evaluation)

이터레이터는 지연 평가(lazy evaluation)를 지원합니다. 즉, 요소가 필요할 때마다 계산하고 반환하기 때문에 성능 최적화에 유리합니다. 이터레이터는 무한한 데이터 시퀀스에서도 사용할 수 있습니다.

5.3. 파이썬의 내장 함수와 이터레이터

파이썬의 많은 내장 함수는 이터레이터와 함께 사용할 수 있습니다. 예를 들어, map(), filter(), zip() 함수는 이터레이터를 반환하며, 이터러블 객체와 함께 사용할 수 있습니다.

numbers = [1, 2, 3, 4, 5]
squared = map(lambda x: x ** 2, numbers)

for num in squared:
    print(num)

이 코드에서 map() 함수는 이터레이터를 반환하며, 이터레이터의 요소를 반복하여 제곱한 값을 출력합니다.

결론

이번 글에서는 파이썬에서 이터러블(Iterable)과 이터레이터(Iterator)의 개념을 살펴보고, 이를 활용하여 반복을 효율적으로 처리하는 방법을 배워보았습니다. 이터러블은 for 루프와 같은 반복문에서 사용할 수 있는 객체이며, 이터레이터는 이터러블의 요소를 순차적으로 반환하는 객체입니다. 이터레이터와 이터러블의 원리를 이해하고, 이를 활용하여 커스텀 반복을 구현해 보세요. 이를 통해 메모리 효율적인 코드 작성과 성능 최적화를 달성할 수 있습니다.


이 글을 통해 파이썬의 이터러블과 이터레이터에 대해 이해하고, 이를 사용하는 방법을 익힐 수 있을 것입니다. 이터레이터를 활용하여 더 효율적인 반복 구조를 구현해 보세요!

+ Recent posts