이터레이터

고봉진·2023년 4월 12일
0

python

목록 보기
2/4

이터레이터

📝 값을 하나씩 꺼내는 객체. 한번에 다 만들어 놓지 않으므로 메모리 효율을 높인다.

  • dir 함수를 사용해 __iter__ 메서드 확인. 들어있다면 이터러블이다.
	>>> it = [1, 2, 3].__iter__()   # 리스트의 이터레이터를 it에 저장
	>>> it.__next__()               # next 메서드로 출력 확인
	1
	>>> it.__next__()
	2
	>>> it.__next__()
	3
	>>> it.__next__()   # 소진될 경우 StopIteration 예외를 발생
	Traceback (most recent call last):
	  File "<pyshell#48>", line 1, in <module>
	    it.__next__()
	StopIteration

반복 가능한 객체에서 __iter__ 메서드를 실행해 이터러블을 얻는다.


이터레이터 만들기

__iter__ 메서드와 __next__ 메서드를 사용해 구현한다

class Counter:
    def __init__(self, stop):
        self.current = 0    # 현재 숫자 유지, 0부터 지정된 숫자 직전까지 반복
        self.stop = stop    # 반복을 끝낼 숫자
 
    def __iter__(self):
        return self         # 현재 인스턴스를 반환
 
    def __next__(self):
        if self.current < self.stop:    # 현재 숫자가 반복을 끝낼 숫자보다 작을 때
            r = self.current            # 반환할 숫자를 변수에 저장
            self.current += 1           # 현재 숫자를 1 증가시킴
            return r                    # 숫자를 반환
        else:                           # 현재 숫자가 반복을 끝낼 숫자보다 크거나 같을 때
            raise StopIteration         # 예외 발생
 
for i in Counter(3):
    print(i, end=' ')

__getitem__ 메서드를 사용하면 인덱스로 접근 가능한 이터레이터를 만들 수 있다.

class Counter:
    def __init__(self, stop):
        self.stop = stop
 
    def __getitem__(self, index):
        if index < self.stop:
            return index
        else:
            raise IndexError
 
print(Counter(3)[0], Counter(3)[1], Counter(3)[2])
 
for i in Counter(3):
    print(i, end=' ')

이터레이터 예시 - zip 객체

views.py

def test(request):
    context = {
        'list': list(range(100)),
        'zip': zip(range(100), range(99, 0, -1)),
    }
    return render(request, 'reviews/test.html', context)

test.html

{% extends 'base.html' %}

{% block content %}
<h1>List: First Loop</h1>
{% for i in list %}
  {{i}}
{% endfor %}

<h1>List: Second Loop</h1>
{% for i in list %}
  {{i}}
{% endfor %}

<h1>Zip: First Loop</h1>
{% for i, j in zip %}
  {{ i }} {{ j }}
{% endfor %}

<h1>Zip: Second Loop</h1>
{% for i, j in zip %}
  {{ i }} {{ j }}
{% endfor %}
{% endblock content %}

출력:

List: First Loop
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
List: Second Loop
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
Zip: First Loop
0 99 1 98 2 97 3 96 4 95 5 94 6 93 7 92 8 91 9 90 10 89 11 88 12 87 13 86 14 85 15 84 16 83 17 82 18 81 19 80 20 79 21 78 22 77 23 76 24 75 25 74 26 73 27 72 28 71 29 70 30 69 31 68 32 67 33 66 34 65 35 64 36 63 37 62 38 61 39 60 40 59 41 58 42 57 43 56 44 55 45 54 46 53 47 52 48 51 49 50 50 49 51 48 52 47 53 46 54 45 55 44 56 43 57 42 58 41 59 40 60 39 61 38 62 37 63 36 64 35 65 34 66 33 67 32 68 31 69 30 70 29 71 28 72 27 73 26 74 25 75 24 76 23 77 22 78 21 79 20 80 19 81 18 82 17 83 16 84 15 85 14 86 13 87 12 88 11 89 10 90 9 91 8 92 7 93 6 94 5 95 4 96 3 97 2 98 1
Zip: Second Loop

리스트는 2번 순회되었지만 이터레이터인 zip 객체는 for문을 두번 실행했음에도 한번만 순회되었다.

>>> a = [*range(10)]
>>> b = range(10)
>>> b
range(0, 10)
>>> dir(b)
['__bool__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index', 'start', 'step', 'stop']
>>> it = b.__iter__()   # range는 immutable sequence 타입 -> 메서드 호출로 이터레이터 생성
>>> it
<range_iterator object at 0x1008f7960>
>>> for i in a:
...     print(i, end=' ')
...
0 1 2 3 4 5 6 7 8 9 
>>> for i in a:
...     print(i, end=' ')
...
0 1 2 3 4 5 6 7 8 9 
>>> for i in it:
...     print(i, end=' ')
...
0 1 2 3 4 5 6 7 8 9 
>>> for i in it:
...     print(i, end=' ')
...
>>>


참고자료

profile
이토록 멋진 휴식!

0개의 댓글