youngfromnowhere
[Python] Iterator 본문
참고자료
Data Structure & Algorithms in Python, Michael T. Goodrich (이하 DSnA)
Python 공식문서(https://docs.python.org/3.12/)
Python 공식문서에서는 Iterator를 다음과 같이 정의하고 있다.
An object representing a stream of data. Repeated calls to the iterator’s __next__() method (or passing it to the built-in function next()) return successive items in the stream. When no more data are available a StopIteration exception is raised instead. At this point, the iterator object is exhausted and any further calls to its __next__() method just raise StopIteration again. Iterators are required to have an __iter__() method that returns the iterator object itself so every iterator is also iterable and may be used in most places where other iterables are accepted.
- stream of data를 나타내는 object이다.
- next(obj) 혹은 obj.__next__()를 호출하면 연속적인 item을 반환한다.
- 더이상 data가 없을땐 StopIteration을 일으킨다.
- 자기자신을 반환하는 __iter__() method를 가지고 있으며 따라서 모든 iterator는 iterable 하다.
다시 말해, iterator class를 구현하기 위해서는 class 내부에 __next__() 와 __iter__()를 위 정의를 만족하도록 구현해야 한다.
그런데 여기서 iterable하다는 것은 어떤 의미일까?
DSnA에서는 iterable을 다음과 같이 정의한다.
An iterable is an object, obj, that produces an iterator via the syntax iter(obj).
즉, 어떤 객체 obj에 대하여 built-in function인 iter(obj)가 iterator를 반환할 경우 obj는 iterable하다.
iter(obj)를 호출하면 obj.__iter__()가 호출되므로, 사용자 정의 class에 적절하게 __iter__()를 구현하면 iterable로 쓸 수 있고, iterator를 구현하기 위해서는 __iter__()가 자기 자신을 반환하도록 구현해야 한다.
itrable이 쓰이는 가장 대표적인 예시는 바로 for loop이다.
for element in iterable :
모든 iterator는 iterable이므로, iterator 또한 for loop에 쓰인다.
(추측) python for loop은 내부적으로 iter() / __iter__()를 호출하여 iterator 객체를 만들고, next() / __next__()를 호출하여 data를 하나씩 꺼내 element에 할당하는 것으로 생각된다..
위에서 알아본 정의를 바탕으로, 직접 iterator와 iterable을 구현해보자.
#!/usr/bin/env python3
class Node:
def __init__(self, element, next):
self._element = element
self._next = next
class MyIterator:
def __init__(self, first, second, third):
self._first = Node(first, None)
self._second = Node(second, None)
self._third = Node(third, None)
self._first._next = self._second
self._second._next = self._third
self.cursor = self._first
def __next__(self):
if self.cursor is None:
raise StopIteration('End of data')
else:
res = self.cursor._element
self.cursor = self.cursor._next
return res
def __iter__(self):
return self
class MyIterable:
def __init__(self, *data):
self._data = data
def __iter__(self):
return MyIterator(*self._data)
if __name__ == '__main__':
my_iterator = MyIterator('first','second','third')
while True:
try:
print(next(my_iterator))
except StopIteration as e:
print("End of my_iterator", e)
break
another_iterator = MyIterator(100, 200, 300)
for i in another_iterator:
print(i)
my_iterable = MyIterable(400, 500, 600)
for i in my_iterable:
print(i)
x = iter(my_iterable) # returns MyIterator object
while True:
try:
print(next(x))
except StopIteration as e:
print("End of x", e)
break
print(x)
파일 실행 결과는 다음과 같았다.
first
second
third
End of my_iterator End of data
100
200
300
400
500
600
400
500
600
End of x End of data
<__main__.MyIterator object at 0x7f6dda6eb9a0>
'Python' 카테고리의 다른 글
| [Python] recursive generator (0) | 2024.12.03 |
|---|---|
| [Python] Generator and yield (0) | 2024.10.23 |
| [Python] pyenv로 가상환경 구축하기. (0) | 2023.09.19 |
| [Python] python의 special methods (0) | 2022.11.17 |
| [Python] Decorator3. Property (0) | 2022.11.16 |