이 노트북은 제이크 반더플라스(Jake VanderPlas)의 A Whirlwind Tour of Python(OReilly Media, 2016)를 기반으로 만들어졌습니다. 이 내용은 CC0 라이센스를 따릅니다. 전체 노트북의 목록은 https://github.com/rickiepark/WhirlwindTourOfPython 에서 볼 수 있습니다.

< 리스트 내포 | 목차 | 모듈과 패키지 >

제너레이터

여기에서 제너레이터 표현식제너레이터 함수를 포함하여 파이썬 제너레이터를 자세히 배워 보겠습니다.

제너레이터 표현식

리스트 내포와 제너레이터 표현식의 차이는 이따금 헷갈립니다. 이 둘의 차이를 간단히 살펴 보겠습니다:

리스트 내포는 대괄호를 사용하고 제너레이터 표현식은 소괄호를 사용합니다

다음은 대표적인 리스트 내포입니다:

반면 다음은 대표적인 제너레이터 표현식입니다:

제너레이터 표현식을 출력하면 내용이 출력되지 않습니다. 제너레이터 표현식의 내용을 출력하는 방법은 list 생성 함수에 전달하는 것입니다:

리스트는 값들의 모음이고, 제너레이터는 값을 만들어내는 한 방식입니다

리스트를 만들 때 실제 일련의 어떤 값들을 만드므로 연관되어 일정량의 메모리가 소모됩니다. 제너레이터를 만들 때는 일련의 값들을 만들지 않고 이런 값들을 만드는 방법을 만듭니다. 둘 다 같은 반복자 인터페이스에 사용할 수 있습니다:

차이는 제너레이터 표현식은 필요할 때까지 실제로 값을 계산하지 않는다는 점입니다. 메모리를 효율적으로 사용할 수 있을 뿐만 아니라 계산 비용도 절감할 수 있습니다! 리스트의 크기는 가용 메모리 범위로 제한되지만 제너레이터의 크기는 제한이 없다는 뜻이 됩니다!

무한 제너레이터 표현식의 한 예는 itertools에 정의된 count 반복자를 사용하여 만들 수 있습니다:

count 반복자는 멈출 때까지 영원히 카운팅할 것입니다. 영원히 실행되는 제너레이터를 만드는 것도 쉽습니다:

적절히 factors 리스트를 확장히키면 에라토스테네스의 체 알고리즘을 사용하여 소수 제너레이터를 구성할 수 있습니다. 조금 후에 이에 대해 더 자세히 알아 보겠습니다.

리스트는 여러번 반복할 수 있지만 제너레이터 표현식은 한번만 사용됩니다

이것이 제너레이터 표현식의 장점 중 하나입니다. 리스트를 사용하면 다음과 같이 쉽게 할 수 있습니다:

하지만 제너레이터 표현식은 한 번 반복하면 사라집니다:

이런 기능 덕택에 반복이 중지되고 다시 시작될 수 있기 때문에 매우 유용합니다:

디스크에 있는 데이터 파일들을 다룰 때 매우 유용합니다. 배치 처리를 할 때 제너레이터가 처리한 파일들을 기억할 수 있습니다.

제너레이터 함수: yield를 사용

이전 절에서 리스트 내포는 비교적 간단한 리스트를 만드는데 좋고 보통의 for 루프는 아주 복잡한 상황에 더 잘 맞습니다. 제너레이터 표현도 동일합니다. yield 문을 사용하는 제너레이터 함수를 사용하여 더 복잡한 제너레이터를 만들 수 있습니다.

동일한 리스트를 만드는 두 가지 방법이 다음에 나타나 있습니다:

비슷하게 동일한 제너레이터를 만드는 두 가지 방법이 있습니다:

제너레이터 함수는 한 번 값을 리턴하는 return 대신 (무한도 가능한) 시퀀스를 반환하는 yield를 사용한 함수입니다. 제너레이터 표현식과 마찬가지로 제너레이터의 상태는 부분 반복 간에 유지됩니다. 새로운 제너레이터를 얻고 싶으면 간단히 함수를 다시 호출하면 됩니다.

예제: 소수 제너레이터

다음 제가 제일 좋아하는 제너레이터 함수의 예를 보겠습니다. 무한한 소수를 생성하는 함수입니다. 전통적인 알고리즘은 다음과 같이 작동하는 에라토스테네스의 체입니다:

아주 충분히 큰 리스트에서 충분한 시간동안 이를 반복하면 원하는 만큼의 소수를 생성할 수 있습니다.

이 로직을 제러레이터 함수에 캡슐화해 보죠:

이것이 전부입니다! 계산이 더 효율적인 에라토스테네스의 체의 구현은 아니지만 제너레이터 함수 문법이 복잡한 시퀀스를 만드는데 얼마나 편리한지 보여줍니다.

< 리스트 내포 | 목차 | 모듈과 패키지 >