파이썬을 학습하다보면 특징적인 반복문이 있다.
C언어의 for루프문은 아래와 같다. 기본 for 문 형식은 c++, c# Java 등 C스타일의 문법이다.
for(int i = 0; i < 5; i++)
{
printf("%d\n");
}
제어문의 흐름이 명확하다.
i는 index 의 줄임이다. 인덱스가 0,1,2,3,4 까지 총 5번을 { } 블록을 실행한다.
*반복문을 하는 이유는:
명령어 블록의 반복 실행을 하거나,
인덱스에 직접 연산을 하거나,
배열 등 메모리를 인덱스에 순차접근을 할 수 있다.
그 밖에 for문을 중첩하거나 if문으로 프로그램의 흐름을 제어할 수 있다.
코드 한 줄이지만 비주얼스튜디오의 디버거를 사용하면 상당히 많은 줄의 기계어 코드가 실행되는 것을 볼 수 있다.
프로그래머는 반복이라는 직관적인 이해를 얻지만 컴퓨터 내부에서는 그보다 복잡한 일을 하고 있다.
파이썬의 문법은 조금 다르다. range를 사용한 for루프는 위의 C언어 스타일의 반복은 잊어버릴 정도로 파이썬 다운 문법이다. 파이썬 초반에 range를 보면서 이해가 쉽지 않은 것은 이터레이터를 처음 접했기 때문이다.
Iterator 는 일반적으로 사용되는 단어는 아니다. 토익을 만점 받아도 이 단어가 나오는지 모르겠다.
컴퓨터 IT용어로써 이해를 해야 한다. 네이버 사전에는
[Noun] (computing) A method capable of performing the same action on every item in a collection.
라고 정의한다. [같은 동작을 반복한다] 는 개념이다. 반복한다는 측면에서는 C언어의 for 루프문과 비슷하다.
파이썬에서는 조금 어렵다. 개념에 대한 깊은 내용은 아래 영문 포스팅을 참고한다.
요약하면.
이터러블(iterable)은 반복할 수 있는 객체이고,
이터레이터(iterator)는 이터러블을 반복시키는 객체이다.
리스트,문자열,튜플,딕셔너리가 대표적인 이터러블이다.
이터레이터는 이들을 조작하는 클래스이다.
그러면 이터레이터를 직접 만들면서 알아보자.
예제> 예제는 range 와 비슷한 동작을 하는 이터레이터이다.
class Range:
def __init__(self, start, stop):
self.current = start
self.stop = stop
def __iter__(self):
return self
def __next__(self):
if self.current < self.stop:
r = self.current
self.current += 1
return r
else:
raise StopIteration
for i in Range(0,10):
print(i)
a,_,c = Range(0,3)
print(a,c)
a,b,c,d,e = Range(0,5)
print(a,b,c,d,e)
list = list(Range(0,5))
print(type(list))
print(list)
클래스로 이터레이터를 정의할 수 있다.
클래스의 생성자와 함께 __iter__ 와 __next__를 정의한다. 이 두개 메소드가 이터레이터를 만든다.
for i in Range(0,10): 를 시작하면 Range는 매개변수를 받아 생성자 __init__를 호출한다.
이터레이터 __iter__()가 호출되면 __next__() 메서드가 반복된다. __next__() 메소드가 실행되면 하나씩 꺼내온다. 다 꺼내오고 더이상 없으면 예외를 발생시킨다.
iterable = Range(0,5).__iter__()
print(iterable.__next__())
print(iterable.__next__())
print(iterable.__next__())
print(iterable.__next__())
print(iterable.__next__())
0부터4까지 반복은 이런 코드와 같다. 초기값이 self.current의 0임에 주의한다. for 문에 들어가면 자동으로 실행되다가 더이상 꺼낼것이 없을 때 StopIteration이 발생된다.
이터레이터로 개별 변수에 할당하거나, 이터러블인 리스트로 형변환할 수 있다. 보면 알겠지만 range(0,5)나 range(5)와 기능이 같다.
리스트나 튜플처럼 순서가 있는 (인덱싱이 가능한) 자료형 뿐만 아니라 딕셔너리처럼 순서가 없어도 반복은 가능하다. 다 꺼낼 때까지 반복한다. 순서가 있는 경우를 시퀀스(sequence) 객체라고 한다.
이런 개념 차이가 들어있어서 파이썬 학습 초기에 for문의 range가 뭘하는지 몰랐던 것이다. range는 iterable이지만 엄밀한 의미의 iterator는 아니라고 한다. 관련 내용은 아래에 나와있다.
range객체는 좀 더 다양하게 사용할 수 있도록 수정된 객체로 볼 수 있다.
위의 포스팅에서는 그런 복잡한 것까지는 몰라도 된다고 한다. 몇년 동안 파이썬을 수천줄을 코딩해도 모르는 경우가 있다고 하니까.
익숙해지다 보면 저절로 알게되는 것들이 많다. 학습 초반에는 너무 많은 설명보다 사용법을 익히는 것이 중요하다.