이터레이터
이터러블 객체
이터러블 객체는 순서가 있는 자료형으로 문자열, 리스트, 튜플, 딕셔너리, range 객체가 있다. 이터러블 객체들은 for 문 안에서 사용할 수 있다. 과연 이터러블 객체는 for 문안에서 어떻게 동작하는지 살펴보자.
>>> print(dir([10, 20, 30]))
['__add__', '__class__', '__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']
>>> print(type([10, 20, 30].__iter__()))
<class 'list_iterator'>
__iter__
는 클래스의 이터레이터 객체를 만들어주는 메서드인 것을 볼 수 있다.
>>> iter_obj = [10, 20, 30].__iter__()
>>> print(iter_obj)
<list_iterator object at 0x7fe1a3069160>
>>> print(dir(iter_obj))
['__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__']
여기서 눈여겨 봐야 할 것은 __next__
라는 메서드이다. 이터러블 객체안에는 __next__
라는 메서드가 포함되어 있다.
>>> print(iter_obj.__next__())
10
>>> print(iter_obj.__next__())
20
>>> print(iter_obj.__next__())
30
>>> print(iter_obj.__next__())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
정리하면 __iter__()
를 통해 이터러블 객체를 만들고, __next__()
함수를 호출해서 이터 하나씩 출력을 하고 더 이상 출력할 것이 없으면 StopIteration이라는 오류를 내뱉는 것이다.
이터레이터 생성
- 이터레이터 클래스를 정의해준다.
__iter__
메서드를 정의해준다.__next__
메서드를 정의해준다.
class Seasons:
def __init__(self):
self.season_list = ['spring', 'summer', 'autumn', 'winter']
self.idx = 0 # 현재 인덱스
self.max_num = 4 # 인덱스의 최대 개수
# __iter__ 메소드 호출시 객체 자기 자신을 리턴
def __iter__(self):
return self
def __next__(self):
if self.idx < self.max_num:
curr_idx = self.idx
self.idx += 1
return self.season_list[curr_idx]
else:
raise StopIteration
이제 Seasons는 우리만의 이터러블 객체로 사용할 수 있다.
>>> for i in Seasons():
... print(i)
...
spring
summer
autumn
winter
Seasons는()를 실행하면 자동으로 __iter__
를 호출해서 이터러블 객체를 만들고, __next__
를 호출해서 하나씩 i에 담게 된다.
>>> iter_obj = Seasons().__iter__()
>>> print(iter_obj.__next__())
spring
>>> print(iter_obj.__next__())
summer
>>> print(iter_obj.__next__())
autumn
>>> print(iter_obj.__next__())
winter
>>> print(iter_obj.__next__())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 15, in __next__
StopIteration