관리 메뉴

클라이언트/ 서버/ 엔지니어 " 게임 개발자"를 향한 매일의 공부일지

파이썬 날아오르기 3 - 이테러이터와 제너레이터 본문

프로그래밍 언어/파이썬

파이썬 날아오르기 3 - 이테러이터와 제너레이터

huenuri 2024. 10. 5. 09:25

이제 이터레이터와 제너레이터에 대해 학습해 볼 것이다. 다음과 같은 예제를 살펴보자.

 

이렇게 for 문과 같은 반복 구문에 적용할 수 있는 리스트와 같은 객체를 '반복 가능 객체'라고 한다.


 

 

 

 

이터레이터란?

이터레이터는 next 함수 호출 시 계속 그다음 값을 리턴하는 객체이다. 리스트는 반복 가능하다. 그렇다면 리스트는 이터레이터일까? 다음을 확인해 보자.

 

리스트는 이터레이터 객체가 아니라는 오류가 발생한다. 즉, 반복 가능하다고 해서 이터레이터는 아니라는 것이다. 하지만 반복 가능하다면 다음과 같이 iter 함수를 이용해 이터레이터로 만들 수 있다.

 

 

리스트를 이터레이터로 변경했으므로 next 함수를 호출해볼 것이다.

 

 

next 함 수를 호출할 때마다 이터레이터 객체의 요소를 차례대로 리턴하는 것을 확인할 수 있다. 하지만 더는 리턴할 값이 없다면 StopIteration 예외가 발생한다.

 

이터레이터의 값을 가져오는 가장 일반적인 방법은 다음과 같이 for문을 이용하는 것이다.

 

for 문을 이용하면 자동으로 값을 호출하므로 next 함수를 따로 쓸 필요도 없고 StopIteration 예외에 신경 쓸 필요도 없다.

 

 

이터레이터는 for 문을 이용하여 반복하고 난 후에는 다시 반복하더라도 더는 그 값을 가져오지 못한다. 즉, for문이나 next로 그 값을 한번 읽으면 그 값을 다시는 읽을 수 없다는 특징이 있다.


 

 

 

 

이터레이터 만들기

iter 함수를 이용하면 리스트를 이터레이터로 만들 수 있다. iter 함수 대신 클래스로 이터레이터를 만들어보자. 이터레이터는 클래스에 __iter__와 __next__라는 2개의 메서드를 구현하여 만들 수 있다.

 

 

클래스에 __iter__ 메서드를 구현하면 해당 클래스로 생성한 객체는 반복 가능한 객체가 된다. __iter__ 메서드는 반복 가능한 객체를 리턴해야 하며 보통 클래스의 객체를 의미하는 self를 리턴한다. 그리고 클래스에 __iter__ 메서드를 구현할 경우 반드시 __next__ 함수를 구현해야 한다.

 

 

이번에는 입력받은 데이터를 역순으로 출력하는 ReverseIterator 클래스를 만들어볼 것이다.

 

 

이를 실행하면 입력받은 데이터를 역순으로 출력한다.


 

 

 

 

제너레이터란?

제너레이터는 이터레이터를 생성해 주는 함수이다. 제너레이터로 생성한 객체는 이터레이터와 마찬가지로 next 함수 호출 시 그 값을 차례대로 얻을 수 있다. 이때 제너레리터에서는 차례대로 결과를 반환하고자 return 대신 yield 키워드를 사용한다.

다음은 가장 간단한 제너레이터의 예시이다.

 

 

mygen 함수는 yield 구문을 포함하므로 제너레이터이다. 제너레이터 객체는 함수를 호출하여 만들 수 있다. 제너레이터의 값을 차례로 얻었다.

 

 

 

yield 문에는 3개가 있으므로 네 번째 next를 호출할 때는 더는 리턴할 값이 없으므로 StopIteration 예외가 발생한다.


 

 

 

 

제너레이터 표현식

이번에는 다음과 같은 예를 살펴본다.

 

1부터 1000까지 각각의 숫자를 제곱한 값을 순서대로 리턴하는 제너레이터이다. 이 예제를 실행하면 총 3번의 next 함수를 호출한다. 제너레이터는 다음과 같은 튜플 표현식으로 좀 더 간단하게 만들 수도 있다.

 

 

여기서 사용한 표현식은 리스트 컴프리헨션 구문과 비슷하다. 다만 리스트 대신 튜플을 이용한 점이 다르다. 이와 같은 표현식을 '제너레이터 표현식'이라고 부른다.


 

 

 

 

제너레이터와 이터레이터

제너레이터는 이터레이터와 서로 비슷하다. 클래스를 이용해 이터레이터를 작성하면 좀더 복잡한 행동을 구현할 수 있따. 이와  달리 제너레이터를 이용하면 간단하게 이터레이터를 만들 수 있다. 따라서 이터레이터의 성격에 따라 클래스 혹은 제너레이터로 만들지 선택해야 한다.

간단한 경우라면 제너레이터 함수나 제너레이터 표현식을 사용하는 것이 가독성이나 유지 보수 측면에서 유리하다. 다음은 제너레리어를 이터레이터 클래스로 구현한 예이다.

 

 


 

 

 

제너레이터 활용하기

제너레이터는 어떤 경우에 사용하면 좋을까?

 

 

1초 간격으로 이 함수가 실행되었다. 이 예제를 제너레이터를 적용해 볼 것이다.

 

 

이번에는 실행 시간이 1초만 소요되고 출력 결과도 다르다. 왜냐하면 제너레이터 표현식으로 인해 longtime_job() 함수가 1회만 호출되기 때문이다. 이러한 방식을 느긋한 계산법이라 부른다. 시간이 오래 걸리는 작업을 한꺼번에 처리하기보다는 필요한 경우에만 호출하여 사용할 때 매우 유용하다.

 


 

 

 

학습을 마치고

몇 시간 동안 이 단원을 학습해 보았다. 생전 처음 들어보는 개념이라 많이 어려웠지만 실습과 함께 병행하니 이해도 잘 되고 재미있었다.

이제 한 단원 학습만 하면 파이썬 문법 공부는 거의 마칠 것 같다.