[TIL - 7 / Python] iterator

haejun-kim·2020년 7월 23일
0

[Python]

목록 보기
14/19
post-thumbnail

iterator (반복자)

값을 순차적으로 꺼내올 수 있는 객체

현재까지는 for 반복문을 사용할 때 range를 사용했다. 예를 들어, 100번을 반복해야한다면

for i in range(100):

과 같이 작성했다. 이 for 반복문이 동작하는것을 조금 자세히 살펴보면 0~99까지의 연속된 숫자를 만들어내는것이 아니라, 0~99까지 값을 차례대로 꺼낼 수 있는 iterator 하나를 만든다. 이후 반복할 때마다 iterator에서 숫자를 하나씩 꺼내서 반복한다. 만약 연속된 숫자를 미리 만들게 되면 만들어야하는 숫자가 아주 많은 경우 메모리를 많이 사용하기 때문에 성능에 불리하다. 그래서 파이썬에서는 iterator만 생성하고 값이 필요한 시점이 되었을 때 값을 만드는 방식을 사용한다. 즉, 데이터 생성을 뒤로 미루는것인데 이러한 방식을 지연 방식(lazy evaluation)이라고 한다.

반복 가능 객체 확인하기

반복 가능한 객체는 말 그대로 반복할 수 있는 객체이다. 예를 들어, 문자열, 리스트, 딕셔너리, 세트가 반복 가능한 객체다. 즉, 요소가 여러개 들어있고, 한번에 하나씩 꺼낼 수 있는 객체를 뜻한다.
하나의 리스트가 반복 가능한 객체인지 확인해보는 방법은

__iter__메소드가 있는지 확인하면 된다.

하나의 리스트를 만들고 dir로 생성한 리스트의 디렉토리를 확인해보자.

print(dir([1,2,3]))

__iter__메소드가 있는것을 확인할 수 있다. 이제 이 메소드를 호출해보자

iterator를 찾았다!

iterator를 변수에 저장하고 메소드를 호출해보면 요소를 차례대로 꺼낼 수 있다.

it = [1,2,3].__iter__()
print(it.__next__()) # 1
print(it.__next__()) # 2
print(it.__next__()) # 3
print(it.__next__()) # StopIteration

__next__메소드는 다음 차례의 값을 꺼내는 역할을 한다.
네번째 출력에서 StopIteration에러가 발생했는데 요소가 세개뿐인 리스트에 __next__()를 사용하여 네번째 요소를 참조하려했기 때문에 발생한 에러다.

for와 반복 가능한 객체

for에 반복 가능한 객체 (range)를 사용했을때의 동작 과정은 다음과 같다.

for에 range(3)을 사용했다면 먼저 range에서 __iter__로 이터레이터를 얻고, 한번 반복할 때마다 __next__로 숫자를 꺼내서 i에 저장하고 지정된 숫자 3이 되면 StopIteration을 발생시켜 반복을 끝낸다.

정리

반복 가능한 객체 : 요소를 한 번에 하나씩 가져올 수 있는 객체
이터레이터 : next 메소드를 사용해서 차례대로 값을 꺼낼 수 있는 객체

반복 가능한 객체(iterable)과 이터레이터(iterator)는 별개의 객체이므로 구분해야한다.
즉, 반복 가능한 객체에서 __iter__메소드로 이터레이터를 얻는다.


Assingment

다음의 코드는 리스트의 요소를 받아 제곱하는 코드이다.
(주석부분은 for 반복문을 사용해서 구현)

L = [1, 2, 3]
# for x in L:
# 	print(x ** 2, end=' ')

I = iter(L) # __iter__ 호출
while True:
    try:
        X = next(I) # __next__ 호출
    except StopIteration:
        break
    print( X**2, end=" ")

for 반복문을 사용하여 구현한 부분을 while 반복문을 사용하여 구현했다.
딕셔너리도 반복가능한 객체이기 때문에 __iter__, __next__, iter(), next() 를 사용할 수 있다.
다음의 딕셔너리에 대한 for문을 while문으로 구현해보자.

D = {'a':1, 'b':2, 'c':3}
for key in D.keys():
    print(key)
  • 풀이
I = iter(D.keys())
while True:
    try:
        x = next(I)
    except StopIteration:
        break
    print(x)

먼저 딕셔너리인 D.keys()로 key를 먼저 추출해주고, iter함수를 통해서 __iter__ 함수를 호출해준다. 함수가 반복문을 진행하면서 next함수를 통해 __next__함수를 호출하여 다음의 D.keys()값으로 다시 호출하는것을 반복한다. 이 과정을 세번 반복한 후 다음 딕셔너리의 키가 없으므로 StopIteration 에러가 발생하게되면 break에 걸려서 반복문이 종료된다.

  • 실행 결과

0개의 댓글