Advanced Python - iterator [2/7]

Seob·2020년 7월 23일
0

TIL

목록 보기
18/36

iterable? iterator? 🤷🏻‍♂️

iterable object는 반복 가능한(iterable) 객체를 말한다. 반복 가능한 객체는 for loop에 넣었을 때 값을 출력할 수 있는 객체라고 생각하면 이해하기 쉽다. iterable obejcts에는 리스트, 튜플, 딕셔너리, 집합 등이 있다.

💡시퀀스 객체와 반복 간능한 객체의 상관 관계

iterator(이터레이터)는 값을 차례대로 꺼낼 수 있는 object(객체)이다. iterator는 iterable한 객체를 내장함수 또는 iterable object의 메소드로 객체를 생성할 수 있다. 파이썬 내장함수인 iter()를 사용해서 iterator 객체를 만들 수 있다.

iterator 객체는 다음과 같이 만들 수 있다.

a = [1, 2, 3]
a_iter = iter(a)
type(a_iter)
<class 'list_iterator>

__iter__ 🐶

iterable 객체는 매직메소드인 __iter__ 메소드를 가지고 있다. dir함수로 확인해볼 수 있다.

>>> b = {1, 2, 3}
>>> dir(b)
['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__iand__', '__init__', '__init_subclass__', '__ior__', '__isub__', '__iter__', '__ixor__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__', 'add', 'clear', 'copy', 'difference', 'difference_update', 'discard', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update']
>>> b_iter = b.__iter__()
>>> type(b_iter)
<class 'set_iterator'>

출력을 해도 이터레이터 객체임을 확인할 수 있다.

print(b.__iter__())
>>>
<list_iterator object at 0x10a999210>

__next__ 🐷

이터레이터를 변수에 저장한 후, __next__ 함수를 호출하면 for loop이 동작하는 것처럼 값을 차례로 꺼내올 수 있다. 우선 변수에 저장한 iterator가 __next__함수가 들어있는지 확인해보려면 다음과 같이 하면 된다.

a = [1, 2, 3]
iterator_a = a.__iter__()
print('dir iterator_a = ', end = ''), print(dir(iterator_a))
>>>
dir iterator_a = ['__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__함수를 호출해서 어떻게 동작하는지 확인해보자.

a = [1, 2, 3]
iterator_a = a.__iter__()

print(iterator_a.__next__())
print(iterator_a.__next__())
print(iterator_a.__next__())
print(iterator_a.__next__())

>>>

1
2
3
Traceback (most recent call last):
  File "practice.py", line 7, in <module>
    print(iterator_a.__next__())
StopIteration

a 리스트의 인덱스 범위를 벗어나자 StopIteration 에러가 발생했다.
__iter____next__를 함께 사용하는 것은 for 문에서 range와 같이 사용하는 것과 같다.

iter(), next() 함수 🐱

iter()next() 함수는 위에서 본 __iter____next__함수를 편하게 사용할 수 있도록 해준다. 이것을 응용하면 iternext를 적용해서 for loop으로 제곱한 것을 while문으로 구현해볼 수 있다.

a = [1, 2, 3, 4]
iterator_a = a.__iter__()

I = iter(a)
while True:
    try:
        X = next(I)
    except StopIteration:
        break
    print(X**2, end=" ")

print()

for i in a:
    print(i**2, end=" ")
    
>>>

1 4 9 16 
1 4 9 16

같은 결과를 출력한다!

위와 마찬가지로 딕셔너리에 대한 for문을 while문으로 구현할 수도 있다.

D = {'a': 1, 'b': 2, 'c': 3}
for key in D.keys():
    print(key, end=" ")

print()

I = iter(D)
while True:
    try:
        K = next(I)
    except StopIteration:
        break
    print(K, end=" ")

>>>

a b c 
a b c

참고

profile
Hello, world!

0개의 댓글