새소식

반응형
Programming Language/Python

[Python] 파이썬 제너레이터(Generator)

  • -
반응형

파이썬 로고 이미지입니다.
Python

파이썬 제너레이터(Generator)


파이썬에서 제너레이터(Generator)는 반복 가능한(iterable) 객체를 생성하는 데 사용되는 특별한 종류의 함수 또는 코드 블록이다.  제너레이터 함수는 일반 함수와 유사하지만, 값을 반환하는 대신 yield 키워드를 사용하여 값을 생성하고 호출자에게 반환한다. 제너레이터 함수는 호출 중간에 상태를 유지하며, 이로 인해 잠시 중단된 후 다시 시작할 수 있다.

 

그렇다면 iter() 함수와 Generator의 차이는 뭘까?

iter() 함수는 반복 가능한 객체를 반복자로 변환하는 함수이고, Generator(제너레이터)는 값을 생성하고 호출 중간에 상태를 유지하는 특별한 종류의 함수나 코드 블록이다. Generator는 반복 가능한(iterable) 객체와 함께 사용되기도 하며, Generator 객체 자체도 반복자(iterator)이다.

 

 

Generator의 기본 구조

def my_generator():
    # 제너레이터 함수의 시작
    yield value1
    yield value2
    # 추가적인 yield 문을 사용하여 값을 생성할 수 있음

Generator는 위의 예제처럼 def 키워드로 함수를 정의한다, 그러면 해당 함수는 제너레이터 함수가 된다. 함수 내에서 yield 키워드를 사용하여 값을 생성하고 반환한다. 또한, yield 문을 통해 값을 생성하고 함수의 실행은 일시 중단된다.

 

제너레이터 함수를 호출하면 제너레이터 객체가 생성되며, 이 객체를 사용하여 값을 생성하고 호출 중간에 상태를 유지하는 특별한 종류의 함수나 코드 블록이다. Generator는 반복 가능한(iterable) 객체와 함께 사용되기도 하며, Generator 객체 자체도 반복자(iterator)이다.

 

예를 들어, 간단한 제너레이터 함수를 사용하여 1부터 5까지의 정수를 생성하는 예제를 살펴보자.

def simple_generator():
    yield 1
    yield 2
    yield 3
    yield 4
    yield 5

gen = simple_generator()

for value in gen:
    print(value)

1부터 5까지의 값을 생성하는 simple_generator 제너레이터를 호출하고, for 루프를 사용하여 값을 반복적으로 출력한다.

 

1
2
3
4
5

실행 결과

 

 

Q. "그렇다면 yield는 위의 예제처럼 언제나 정적으로 밖에 선언을 못하는걸까?"

yield 문은 제너레이터 함수 내에서 동적으로 값을 생성하고 반환하는 것이 아니라, 해당 함수가 호출될 때 실행되며 그 시점에서 정적으로 값을 생성하고 반환한다. 따라서 yield 문은 함수 내에서 일반적으로 정적으로 사용된다. 이것은 제너레이터의 주요 특성 중 하나이다. 하지만 yield 문의 인자로 변수나 수식을 사용하여 값을 동적으로 생성하는 것은 가능하다. 예를 들어 다음과 같이 변수나 수식을 사용하여 yield 문을 동적으로 설정할 수 있다.

 

def dynamic_generator(n):
    for i in range(n):
        yield i * 2

gen = dynamic_generator(5)

for value in gen:
    print(value)

dynamic_generator 제너레이터 함수는 yield 문 내에서 i * 2와 같은 수식을 사용하여 값을 동적으로 생성한다. 이렇게 하면 yield 문이 호출될 때마다 i에 따라 다른 값을 생성하게 된다. 따라서 yield는 함수 내에서 실행될 때 동적으로 값을 생성할 수 있는 여러 가지 방법을 제공하지만 주로 정적인 값이나 계산된 값 반환에 사용된다.

 

0
2
4
6
8

실행 결과

 

 

또 다른 예제로 문자열의 길이에 따라 다른 문자열을 동적으로 생성하는 제너레이터 함수를 살펴보자.

def length_based_generator(strings):
    for string in strings:
        yield f"The length of '{string}' is {len(string)} characters."

string_list = ["apple", "banana", "cherry"]

gen = length_based_generator(string_list)

for result in gen:
    print(result)

length_based_generator 제너레이터 함수는 입력 문자열의 길이에 따라 문자열을 동적으로 생성하고 출력한다.

 

The length of 'apple' is 5 characters.
The length of 'banana' is 6 characters.
The length of 'cherry' is 6 characters.

실행 결과

 

이러한 예제에서 yield 문을 사용하여 제너레이터가 동적으로 값을 생성하고 반환함을 확인할 수 있다.

 

Q. "그럼 제너레이터는 보통 하나의 함수에서 여러 개의 값을 반환 받을 때 사용하는게 적절한가?"

제너레이터는 보통 반복적인 작업을 수행하며 하나의 함수에서 여러 값을 생성하고 반환할 때 사용된다. 아래는 제너레이터가 유용한 일반적인 케이스들이다.

 

사례 내용
대량 데이터 처리 제너레이터는 대량의 데이터를 효율적으로 처리할 때 유용하다. 데이터를 메모리에 모두 로드하지 않고 필요한 만큼 생성할 수 있다. 이는 메모리 절약과 성능 향상에 도움이 된다.
무한 시퀀스 제너레이터를 사용하여 무한 시퀀스(예 : 피보나치 수열, 소수 생성)를 생성할 수 있다. 무한 시퀀스를 생성하는 데는 제너레이터가 이상적이다.
데이터 스트림 처리 파일이나 네트워크 연결과 같은 데이터 스트림을 처리할 때 제너레이터는 매우 유용하다. 데이터 스트림을 한 번에 읽을 수 없는 경우에도 제너레이터를 사용하여 데이터를 조금씩 읽을 수 있다.
연속적인 계산 복잡한 계산을 여러 단계로 나누어 수행할 때, 각 계산 단계마다 결과를 생성하고 다음 계산에 활용하는 제너레이터를 사용할 수 있다.
중첩 반복 제너레이터를 중첩하여 여러 반복 루프를 처리할 때 유용하다. 중첩된 루프에서 각 단계의 값을 생성하고 처리할 수 있다.

 

제너레이터는 데이터를 게으르게 생성하므로, 필요한 경우에만 값을 생성하고 반환한다. 이로써 메모리와 처리 시간을 절약할 수 있다. 따라서 다양한 상황에서 여러 값을 생성하고 반환해야 할 때, 제너레이터는 매우 유용한 도구이다.

 

 

읽어주셔서 감사합니다.

728x90
반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.