Python 기초

이터레이터와 제너레이터

이터레이터

우리는 for 루프를 이용하여 리스트 안의 요소들에 대하여 반복할 수 있었습니다.

for i in [1, 2, 3, 4]:
    print(i, end=" ")

 

<실행 결과>

1 2 3 4

 

또 문자열의 각 문자에 대해서도 반복할 수 있었으며 딕셔너리, 파일도 마찬가지였습니다.

for c in "python":
    print(c, end=" ")

 

<실행 결과>

p y t h o n

 

파이썬에서는 for 루프와 함께 사용할 수 있는 여러 종류의 객체가 있으며 이들 객체는 이터러블 객체(iterable object)라고 불립니다.

이터레이션(iteration)이 반복을 의미하므로 이터러블은 "반복할 수 있는 것"이라고 해석할 수 있습니다.

 

객체가 이터러블 객체가 되려면 다음과 같은 2개의 메소드를 구현하여야 합니다.

  • __iter__() 는 이터러블 객체 자신을 반환합니다.
  • __next__() 는 다음 반복을 위한 값을 반환합니다. 만약 더 이상의 값이 없으면 StopIteration 예외를 발생하면 됩니다.

 

예를 들어서 MyCounter 클래스를 이터러블 클래스로 정의한 후 MyCounter 객체를 for 루프에서 사용해봅시다.

class MyCounter(object):
    # 생성자 메소드를 정의합니다.
    def __init__(self, low, high):
        self.current = low
        self.high = high

    # 이터레이터 객체로서 자신을 반환합니다.
    def __iter__(self):
        return self

    def __next__(self):
        # current가 high 보다 크면 StopIteration 예외를 발생합니다.
        # current가 high 보다 작으면 다음 값을 반환합니다.
        if self.current > self.high:
            raise StopIteration
        else:
            self.current += 1
            return self.current - 1

c = MyCounter(1, 10)
for i in c:
    print(i, end = ' ')

 

<실행 결과>

1 2 3 4 5 6 7 8 9 10

 

제너레이터

파이썬 제너레이터는 2.3 버전부터 도입되었습니다. 제너레이터(generators)는 키워드 yield를 사용하여서 함수로부터 이터레이터를 생성하는 하나의 방법입니다.

우리는 함수를 yield 문장을 사용하여 제너레이터로 만들 수 있습니다.

# 함수를 제너레이터로 정의합니다. yield 문장을 사용합니다.
def myGenerator():
    yield 'first'
    yield 'second'
    yield 'third'

 

위의 예제에서 우리는 yield 문장을 사용하여 간단한 제너레이터를 생성하였습니다. 정의된 제너레이터를 for 루프에서 이터레이터로 사용할 수 있습니다.

# 함수를 제너레이터로 정의합니다. yield 문장을 사용합니다.
def myGenerator():
    yield 'first'
    yield 'second'
    yield 'third'

for word in myGenerator():
    print(word)

 

<실행 결과>

first
second
third

 

앞의 이터레이터와 비교해보면 이터레이터는 클래스를 이용하여 이터러블 객체를 생성하는 것이고 제너레이터는 함수를 이용하여 이터러블 객체를 생성하는 것입니다.

MyCounter 클래스와 유사한 제너레이터 함수를 정의해봅시다.

def MyCounterGen(low, high):
    while low <= high:
        yield low
        low += 1

for i in MyCounterGen(1, 10):
    print(i, end = ' ')

 

<실행 결과>

1 2 3 4 5 6 7 8 9 10

 

클로저

클로저(closure)는 함수에 의하여 반환되는 함수입니다. 우리는 코드의 중복을 막기 위하여 클로저를 사용합니다. 아래의 예제에서 숫자를 합하는 간단한 클로저를 생성해봅시다.

# 고정된 숫자에 전달받은 숫자를 더하는 함수를 반환합니다.
def addNumber(fixedNum):
    def add(number):
        return fixedNum + number
    return add

func = addNumber(10)
print(func(20))

 

<실행 결과>

30

 

도전 과제

피보나치 수열이란 앞의 두 수의 합이 바로 뒤의 수가 되는 수열을 의미합니다. 다음과 같은 그림도 피보나치 수열로 그릴 수 있습니다.

피보나치 수열에 대한 이미지 검색결과

피보나치 수열들의 수들을 생성하는 이터레이터 클래스를 정의해봅시다.

 

<실행 결과>

1 1 2 3 5 8 13 21 34