이터레이터(Iterator)
iterate: 반복하다
이터레이터
대부분의 프로그래밍 언어에는 for
루프처럼 반복문이 존재하는데, 일반적으로 배열을 대상으로 반복문을 사용합니다.
파이썬에서는 list
, tuple
, str
, set
등 다양한 컨테이너 객체에 대해 반복문을 사용할 수 있습니다.
이들은 공통점이 있는데, 바로 내부적으로 __iter__
메서드를 가지고 있다는 것입니다.
파이썬에서는 모든 것이 객체입니다.
반복문을 사용할 때 아마 가장 많이 사용할 list
, tuple
형태의 데이터도 결국엔 객체이며, 이 안에 __iter__
메서드가 내장되어 있는 것을 직접 확인할 수 있습니다.
>>> dir([1, 2, 3])
['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
따라서 이 메서드의 존재는 해당 객체가 반복 가능하다는 (반복문의 대상이 될 수 있는) 성질을 갖고 있다고 알려주는 셈입니다.
__iter__
메서드에는 해당 객체를 대상으로 반복하는 방법을 정의해야 합니다.
그렇다면 이 메서드를 어떤 식으로 구현해야 제대로 동작할까요?
__iter__
메서드는 __next__
메서드를 가지고 있는 객체를 반환해야 합니다.
조금 복잡하게 들릴 수 있지만, __next__
메서드는 다음 순서의 값을 반환하는 메서드일 뿐입니다.
간단한 예시가 아래에 있습니다.
class Counter:
"""__next__ 메서드를 구현함"""
def __init__(self):
self.count = 0
def __next__(self):
"""다음 순서의 값을 반환함"""
self.count += 1
if self.count > 10:
raise StopIteration
return self.count
class Iterable:
"""__iter__ 메서드를 가지므로 반복문의 대상이 될 수 있음"""
def __iter__(self):
"""__next__ 메서드를 가지는 객체를 반환함"""
return Counter()
if __name__ == "__main__":
iterable_obj = Iterable()
for x in iterable_obj:
print(x)
Counter
클래스의 __next__
메서드는 앞서 언급한 대로 다음 순서의 값을 반환하는 역할을 수행합니다. 만약 더 이상 반환할 값이 없다면 StopIteration
예외를 일으켜 반복의 끝을 알려야 합니다.
이보다 더 간단한 예시로 아래처럼 __iter__
메서드와 __next__
메서드를 한 클래스에서 구현해도 되지만 멀티 프로세싱과 같은 동시성 기법을 사용할 때 문제가 될 수 있다고 합니다.
class Iterable:
def __init__(self):
self.count = 0
def __next__(self):
self.count += 1
if self.count > 10:
raise StopIteration
return self.count
def __iter__(self):
return self
if __name__ == "__main__":
iterable_obj = Iterable()
for x in iterable_obj:
print(x)
빌트인(built-in) 함수
__next__
메서드와 __iter__
메서드는 여타 다른 매직 메서드 (또는 던더 메서드)와 마찬가지로 빌트인 함수를 제공합니다.
iter()
함수는 주어진 대상(컬렉션)에 요소 하나씩 접근하는 이터레이터를 생성하며, 안에는 __next__()
메서드가 구현됩니다. 즉, __iter__
메서드와 __next__
메서드 모두 하나의 객체에서 자동으로 구현되어 생성됩니다.
>>> s = 'abc'
>>> it = iter(s)
>>> it
<str_iterator object at 0x1102df370>
>>> next(it)
'a'
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> dir(it)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__length_hint__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__']
정리
__iter__
메서드를 가지는 않는 객체라면 반복 가능한 객체라고 부를 수 없습니다.- 실제로 반복이 가능한 객체가 되려면
__next__
메서드를 제공해야 합니다. iter()
함수와next()
함수 또한 빌트인 함수로서 제공됩니다.
출처
Author And Source
이 문제에 관하여(이터레이터(Iterator)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@ghwn/파이썬-비동기-프로그래밍저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)