본문 바로가기
Python/기초

[파이썬/Python] Iterable과 Iterator에 대한 명쾌한 정리

by 모두의 케빈 2023. 7. 6.

Iterable과 Iterator의 정의


Iterable 객체의 정의와 확인하는 방법

 

Iterable은 내부에 __iter__ 메서드가 있는 모든 객체이며, 순회할 수 있는 객체이고 재사용이 가능합니다. Iterable에는 list, 문자열, dictionary, tuple, set과 같은 자료 유형이 이에 해당합니다.

객체가 Iterable인지 확인하는 방법은 아래 코드를 참고해 주세요.

from typing import Iterable

print(isinstance([1,2,3], Iterable))               # True
print(isinstance('abcd', Iterable))                # True
print(isinstance({1:'cal', 2:'jun'}, Iterable))    # True
print(isinstance((5,6,7), Iterable))               # True
print(isinstance(set([5,6,7]), Iterable))          # True

 

내부에 __iter__ 메서드가 있으면 모두 Iterable 객체로 인식할까요? 놀랍게도 그렇습니다.

아무 내용이 없는 의미 없는 'Temp'라는 Class를 만들었습니다. 그리고 그 안에 __iter__ 메서드를 선언만 했습니다. 그랬더니 파이썬은 Temp라는 Class를 Iterable 객체로 인식하고 있음을 확인할 수 있습니다.

class Temp:
    def __init__(self):
        pass
    
    def __iter__(self, start, end):
        pass
        
        
print(isinstance(Temp(), Iterable))  # True

 

 

Iterator 객체의 정의와 확인하는 방법

 

Iterator는 Iterable 객체에서 __iter__ 메서드를 통해 생성되는 객체입니다. 상태가 존재하기 때문에 한번 순회하면 재사용할 수 없습니다. 내부에 존재하는 __next__ 메서드를 통해 다음 값을 하나씩 차례대로 반환합니다. 마지막 원소까지 접근하여, 더 이상 반환할 수 있는 값이 없다면 StopIteration 에러를 반환하며 순회를 종료합니다.

list_a = [1,2,3,4,5]
itorator_a = list_a.__iter__()

print(type(itorator_a))    # <class 'list_iterator'>

 

iterator 객체인지 확인하는 방법은 아래 코드를 참고해 주세요.

from typing import Iterator


print(isinstance(itorator_a, Iterator)) # True

 

 

Iterable과 Iterator의 차이


 

Iterable 객체에서 __iter__ 메서드를 통해 생성되는 것이 Iterator 객체라고 말씀드렸습니다.

두 객체의 첫 번째 차이점은 Iterable 객체의 경우 순회 당하는 객체이고, Iterator 객체는 순회를 주관하는 객체라는 점입니다. 이 개념에 대해서는 뒷부분에 더 상세하게 설명드리도록 하겠습니다.

 

두 객체의 두 번째 차이점은 Iterable은 재사용할 수 있지만, Iterator는 재사용할 수 없습니다. 먼저 Iterable 객체인 list를 for 문으로 출력해 보겠습니다. 

list_a = [1,2,3,4]

for i in list_a:
    print(i, end = ' ')
    
# 코드 실행 결과값: 1 2 3 4

 

그리고 아래의 코드를 3번 정도 반복해 보겠습니다. 몇 번을 반복하더라도 "1 2 3 4"라는 값이 잘 출력됩니다.

for i in list_a:
    print(i, end = ' ')
    
# 코드 결과값: 1 2 3 4

 

list_a에서 __iter__ 메서드를 통해 iterator_a를 만들었습니다.

list_a = [1,2,3,4]

iterator_a = list_a.__iter__()
print(type(iterator_a)) # <class 'list_iterator'>

 

그리고 iterator_a를 for문으로 한번 출력해 보겠습니다. "1 2 3 4"의 값이 잘 출력됩니다.

for i in iterator_a:
    print(i, end = ' ')
    
# 코드의 결과값: 1 2 3 4

 

그럼 다시 한번 for문으로 출력해 볼까요? 놀랍게도 아무 값도 출력되지 않는 것을 확인할 수 있습니다. 이는 iterator_a가 재사용이 불가능한 1회성 객체이기 때문입니다. iterator_a를 처음 순회할 때, iterator_a의 상태는 '1'입니다.

1을 출력했으면, 다음 상태인 '2'로 이동합니다. 이렇게 마지막까지 순회하면 iterator_a의 상태는 '4'가 됩니다. 4 다음의 값, 상태는 없으므로 iterator_a는 다시 선언해주지 않는 이상, 재사용할 수 없습니다. 

for i in iterator_a:
    print(i, end = ' ')
    
    
# 아무 값도 출력되지 않음

 

 

for문으로 살펴보는 Iterable과 Iterator 객체의 동작 원리


 

Iterable 객체와 Iterator의 첫 번째 차이점이 Iterable 객체는 순회를 당하고, Iterator 객체는 순회를 한다고 말씀드렸습니다. 먼저 for문에 Iterable 객체를 넣으면 값이 어떻게 출력되는지 확인해 보겠습니다.

list_a = [1,2,3,4]

for i in list_a:
    print(i)
    
# 위 코드의 결과값
1
2
3
4

 

이는 for 문을 배우신 분이라면 직관적으로 유추할 수 있는 결과입니다. 이 원리에 대해 설명드리겠습니다.

 

1. for문에 Iterable 객체를 넣어주면  내부의 __iter__ 메서드를 통해 임의의 Iterator를 만듭니다.

2. 만들어진 Iterator 내부의 __next__ 메서드를 통해 Iterator의 끝까지 값이 반환합니다.

3. Iterator의 마지막에 도달하면 StopIteration 에러를 발생시킵니다.

4. StopIteration 에러가 발생하면 for문을 종료합니다.

 

따라서 위 for문의 코드는 아래와 같이 바꿀 수 있습니다.

list_a = [1,2,3,4]

iterator_a = list_a.__iter__()

iterator_a.__next__() # 1
iterator_a.__next__() # 2
iterator_a.__next__() # 3
iterator_a.__next__() # 4
iterator_a.__next__() # StopIteration

 

이와 같은 작동 원리 때문에 Iterable 객체는 순회당하고, Iterator 객체는 순회를 주관한다고 표현할 수 있습니다. Iterable 객체를 순회하기 위해서 Iterator 객체를 수작업으로 선언할 필요는 없고, 반복문을 활용하면 이 과정을 자동화해 줍니다.

 

이상으로 Iterable, Iterator 객체에 대해 정리해 봤고, 다음 시간에는 직접 이 두 객체를 구현해 보는 시간을 갖도록 하겠습니다.

댓글