본문 바로가기
개발/Python

[파이썬, Python] 제너레이터 활용법 총정리

by 꾀돌이 개발자 2024. 7. 15.
반응형

 

제너레이터 활용하기

 

 

- 파이썬의 제너레이터(generator)는 반복 가능한(iterable) 객체를 생성하는데 사용되는 특수한 함수입니다.

- 제너레이터는 일반 함수와 비슷하지만, 값을 반환할 때 return 키워드 대신 yield 키워드를 사용합니다.

- 특히 큰 데이터 처리와 메모리 최적화가 필요한 상황에서 유용합니다.

 

 

[제너레이터 함수 정의]

 

 

- 일반적인 함수와 매우 유사하지만, return 대신 yield 키워드를 사용하여 제너레이터를 만듭니다.

def my_generator():
    yield 1
    yield 2
    yield 3

- 이 함수는 호출될 때 제너레이터 객체를 반환합니다. 이를 반복(iterate)하여 값을 얻을 수 있습니다.

gen = my_generator()
print(next(gen))  # 출력: 1
print(next(gen))  # 출력: 2
print(next(gen))  # 출력: 3
print(next(gen))  # StopIteration 예외 발생

- StopIteration 예외는 파이썬에서 반복자(iterator)가 더 이상 반환할 값이 없음을 나타내기 위해 사용됩니다.

 

 

[제너레이터 표현식]

 

 

- 리스트 컴프리헨션과 유사하게 제너레이터 표현식(generator expression)을 사용할 수 있습니다.

- 제너레이터 표현식은 메모리를 절약하며, 대괄호 대신 소괄호를 사용하여 정의합니다.

gen_expr = (x * x for x in range(5))
for value in gen_expr:
    print(value)

 

 

[제너레이터의 사용 예시]

 

 

- 큰 데이터 처리

  • 대량의 데이터를 메모리에 모두 로드하지 않고 순차적으로 처리할 때 유용합니다.
def read_large_file(file_path):
    with open(file_path) as file:
        for line in file:
            yield line

for line in read_large_file('large_file.txt'):
    print(line)

 

- 무한 수열 생성

  • 무한 수열을 생성하는 제너레이터를 만들 수 있습니다.
def infinite_sequence():
    num = 0
    while True:
        yield num
        num += 1

gen = infinite_sequence()
for i in range(5):
    print(next(gen))
  • for문의 range 범위를 무한히 늘려도 계속 print가 가능합니다.

 

 

[제너레이터 메서드]

 

 

- send(value): 제너레이터 내부로 값을 보내고, yield 표현식의 결과로 그 값을 받습니다.

- throw(type, [value, [traceback]]): 제너레이터 내에서 예외를 발생시킵니다. (특정 예외가 발생했을 때 제너레이터의 실행을 제어하거나 중단함.)

- close(): 제너레이터를 종료시킵니다.

def generator_with_exception_handling():
    try:
        while True:
            try:
                value = (yield)
                print(f'Received: {value}')
            except ValueError:
                print('ValueError handled inside generator')
    except GeneratorExit:
        print('Generator was closed')

gen = generator_with_exception_handling()
next(gen)  # 제너레이터 시작

gen.send('Hello')  # 출력: Received: Hello
gen.send('World')  # 출력: Received: World

# 제너레이터 내에서 ValueError 발생시키기
gen.throw(ValueError)  # 출력: ValueError handled inside generator

gen.close()  # 출력: Generator was closed
  • value = (yield) 부분은 제너레이터가 실행을 일시 중지하고 외부에서 값을 받을 준비가 되었음을 의미합니다. send() 메서드를 사용하여 이 지점에서 제너레이터로 값을 보낼 수 있습니다.
  • next(gen)은 제너레이터를 처음 시작합니다. 이 호출은 제너레이터가 첫 번째 yield 문에서 멈출 때까지 실행됩니다. 이 시점에서 제너레이터는 실행 상태를 유지하며 외부에서 값을 받을 준비가 됩니다

 

 

[제너레이터의 특징]

 

 

1. yield 키워드

  • yield는 함수 내에서 사용되어 제너레이터를 만듭니다.
  • yield는 값을 반환하고 함수의 실행 상태를 저장합니다. 다음에 제너레이터가 호출되면 저장된 상태로부터 실행을 재개합니다.

 

2. 반복자 인터페이스 구현

  • 제너레이터는 반복자(iterator) 인터페이스를 구현합니다. 즉, __iter__() 및 __next__() 메서드를 자동으로 제공합니다.

 

3. 메모리 효율성

  • 제너레이터는 한번에 하나의 값만 메모리에 저장하기 때문에, 큰 데이터 집합을 처리할 때 메모리 효율적입니다.

 

 

[ 제너레이터의 장점 요약]

 

 

 

- 메모리 효율성: 한 번에 하나의 항목만 생성하기 때문에 메모리 사용량이 적습니다.

 

- 읽기 쉬운 코드: 복잡한 반복 처리를 단순화할 수 있습니다.

 

- 지연 평가: 필요한 시점에 값이 생성되어 효율적인 계산이 가능합니다.

 

 

반응형