본문 바로가기

언어/Python

[ Python ] 제너레이터(Generators) 사용하기

반응형

파이썬의 제너레이터(Generators)는 반복 가능한 객체를 생성하는 특별한 함수입니다.
제너레이터는 일반 함수와 유사하지만, 값을 반환할 때 return 대신 yield 키워드를 사용합니다.
제너레이터는 호출될 때마다 값을 하나씩 반환하며, 호출이 멈추면 이전 상태를 유지하여 다음 호출에서 이어서 실행됩니다.
이는 큰 데이터 집합을 처리할 때 메모리 사용을 최소화할 수 있는 이점을 제공합니다.

1. 제너레이터의 기본 개념

제너레이터 함수

제너레이터 함수는 yield 키워드를 사용하여 값을 하나씩 반환합니다.

def simple_generator():
    yield 1
    yield 2
    yield 3

gen = simple_generator()

print(next(gen))  # 1
print(next(gen))  # 2
print(next(gen))  # 3

제너레이터는 next() 함수 호출을 통해 순차적으로 값을 반환합니다. 더 이상 반환할 값이 없으면 StopIteration 예외가 발생합니다.

제너레이터 표현식

제너레이터 표현식은 리스트 컴프리헨션과 유사하지만, 대괄호 대신 소괄호를 사용합니다.

gen_expr = (x * x for x in range(3))

print(next(gen_expr))  # 0
print(next(gen_expr))  # 1
print(next(gen_expr))  # 4

2. 제너레이터의 장점

  1. 메모리 효율성: 한 번에 모든 값을 메모리에 저장하지 않고, 필요할 때마다 값을 생성하므로 메모리를 절약할 수 있습니다.
  2. 지연 평가: 값을 필요한 순간까지 계산하지 않으므로 계산 비용을 분산시킬 수 있습니다.
  3. 복잡한 이터레이터 작성: 제너레이터는 복잡한 이터레이터를 간단하고 직관적으로 작성할 수 있게 해줍니다.

3. 제너레이터 사용 예제

예제 1: 간단한 제너레이터

def countdown(n):
    while n > 0:
        yield n
        n -= 1

for num in countdown(5):
    print(num)

출력:

5
4
3
2
1

예제 2: 무한 제너레이터

def infinite_sequence():
    num = 0
    while True:
        yield num
        num += 1

gen = infinite_sequence()
for _ in range(10):
    print(next(gen))

출력:

0
1
2
3
4
5
6
7
8
9

예제 3: 파일 읽기 제너레이터

큰 파일을 읽을 때, 파일의 모든 내용을 한 번에 메모리에 로드하지 않고 한 줄씩 처리할 수 있습니다.

def read_file_line_by_line(file_path):
    with open(file_path, 'r') as file:
        while True:
            line = file.readline()
            if not line:
                break
            yield line

for line in read_file_line_by_line('example.txt'):
    print(line.strip())

4. 제너레이터의 고급 기능

send() 메서드

제너레이터는 send() 메서드를 통해 외부에서 값을 받아들일 수 있습니다.

def generator():
    while True:
        value = yield
        print(f"Received: {value}")

gen = generator()
next(gen)  # 제너레이터를 초기화
gen.send(1)  # Received: 1
gen.send(2)  # Received: 2

throw() 메서드

제너레이터 내부에서 예외를 발생시킬 수 있습니다.

def generator():
    try:
        yield 1
    except ValueError:
        yield 'Error: ValueError'
    yield 2

gen = generator()
print(next(gen))  # 1
print(gen.throw(ValueError))  # Error: ValueError
print(next(gen))  # 2

close() 메서드

제너레이터의 실행을 종료할 수 있습니다.

def generator():
    yield 1
    yield 2

gen = generator()
print(next(gen))  # 1
gen.close()
# 이후 next() 호출은 StopIteration 예외를 발생시킴

5. 요약

파이썬의 제너레이터는 메모리 효율적이고 유연한 반복 처리를 가능하게 하는 강력한 도구입니다. yield 키워드를 사용하여 값을 하나씩 반환하며, 제너레이터 표현식을 통해 간단하게 생성할 수도 있습니다. 제너레이터의 고급 기능인 send(), throw(), close()를 사용하면 더 복잡한 제너레이터 로직을 구현할 수 있습니다. 이러한 특성은 큰 데이터 집합을 처리하거나 지연 평가가 필요한 상황에서 특히 유용합니다.

반응형