[Python] 리스트 반환 보단 제너레이터 사용

미남잉·2023년 1월 13일
1

이미지 출처: 파이썬 코딩 도장


시퀀스를 결과로 만들어내는 함수를 만들 때 가장 간단한 방법은 원소들이 모인 리스트를 반환하는 것입니다.

예로 문자열에서 찾은 단어의 인덱스를 반환하고 싶을 떄, append 메서드를 사용해 리스트에 결과를 추가하고 함수 마지막에 리스트를 반환합니다.


def index_words(text):
    result = []
    if text:
        result.append(0)
    for index, letter in enumerate(text):
        if letter == ' ':
            result.append(index + 1)
    return result

address = '컴퓨터(영어: Computer, 문화어: 콤퓨터, 순화어:전산기)는 진공관'
result = index_words(address)
print(result[:10])

[0, 8, 18, 23, 28, 38]


위 함수의 문제점

  1. 코드에 잡음이 많으며 핵심을 알아보기 어려움
  2. 새로운 결과를 찾을 때마다 append 메서드 호출
  3. 메서드 호출이 커서 리스트에 추가될 값 (index + 1 ) 의 중요성을 희석시킴

이 함수를 개선하는 방법은 제너레이터를 ****사용하는 것!


def index_words_iter(text):
    if text:
        yield 0
    for index, letter in enumerate(text):
        if letter == ' ':
            yield index + 1

it = index_words_iter(address)
print(next(it))
print(next(it))

0
8


위 함수가 호출되면 제너레이터 함수가 실제로 실행되지 않고 즉시 이터레이터를 반환합니다. 이터레이터가 next 내장 함수를 호출할 때마다 이터레이터는 제너레이터 함수를 다음 yield 식까지 진행시킵니다. 제너레이터가 yield에 전달하는 값은 이터레이터에 의해 호출하는 쪽에 반환됩니다.

위와 비교했을 때, 반환하는 리스트와 상호작용하는 코드가 사라져 index_words_iter 함수가 훨씬 읽기 쉽습니다.

대신 결과는 yield 에 의해 전달됩니다.

제너레이터가 반환하는 이터레이터를 리스트 내장함수에 넘기면 필요할 때 제너레이터를 쉽게 리스트로 반환할 수 있습니다.


result = list(index_words_iter(address))
print(result[:10])

[0, 8, 18, 23, 28, 38]


index_words 의 문제점으로 반환하기 전 모든 결과를 리스트에 저장해야한다는 점이 있었는데, 입력이 크다면 메모리 문제로 중단될 수 있습니다.

반면 같은 함수를 제너레이터로 만들 때, 메모리 크기를 제한할 수 있으므로 길이가 길어도 쉽게 처리 가능합니다.

아래 코드는 파일에서 한 번에 한 줄씩 읽어 한 단어씩 출력하는 제너레이터를 정의한 코드입니다.


def index_file(handle):
    offset = 0
    for line in handle:
        if line:
            yield offset
        for letter in line:
            offset += 1
            if letter == ' ':
                yield offset

이 함수의 작업 메모리는 입력 중 가장 긴 줄의 길이로 제한됩니다.


import itertools
with open('address.txt', 'r', encoding='utf-8') as f:
    it = index_file(f)
    results = itertools.islice(it, 0, 10)
    print(list(results))

[0, 8, 18, 23, 28, 38]


제너레이터를 정의할 때 알아둬야 할 점은 제너레이터가 반환하는 이터레이터에 상태가 있기 때문에 호출하는 쪽에서 재사용이 불가능하다는 점입니다.

address.txt : 컴퓨터(영어: Computer, 문화어: 콤퓨터, 순화어:전산기)는 진공관


정리

  1. 제너레이터 사용하면 결과를 리스트에 합쳐서 반환하는 것보다 더 깔끔함
  2. 제너레이터가 반환하는 이터레이터는 제너레이터 함수의 본문에서 yield가 반환하는 값들로 이뤄진 집합을 만듦
  3. 제너레이터를 사용하면 작업 메모리에 모든 입력과 출력을 저장할 필요가 없으므로 입력이 아주 커도 출력 시퀀스를 만들 수 있습니다.
profile
Tistory로 이사갔어요

0개의 댓글