ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 66 - (파이썬) 이터러블, 이터레이터, 제너레이터 함수, 제너레이터 표현식
    study with Q - 파이썬 2024. 7. 9. 11:01

    제너레이터 (generator)

    : 파이썬의 특수한 문법구조. 이터레이터를 직접 만들 때 사용하는 코드. 함수 내부에 yield 키워드를 사용하면 해당 함수는 제너레이터 함수가 되며 일반 함수와 다르게 함수를 호출해도 함수 내부의 코드가 실행되지 않는다.

     

    참고)

    더보기

    이터러블

    :  반복할 수 있는 것 / aka 반복문 뒤에 넣을 수 있는 것

    Iterate + able

    eg) 리스트, 튜플, 딕셔너리 등

     

    이터레이터

    : 반복하는 것 / 이터러블을 만드는 방법 중 하나

    Iterate + or

    이터레이터를 만드는 방법

    - 제너레이터 표현식 사용

    - 제너레이터 함수 사용

    - 이터레이터 클래스  (투머치 고급)

    기억나니.... #리스트 내포

    [
      #표현식
      표현식
      #반복문
      for 요소 in 반복할수있는것
      #조건문
      if 조건문
    ]

     

    1부터 10까지의 정수를 제곱하는 프로그램을 리스트 내포를 이용해서 만들어 본다면 다음과 같다.

    l = [
      #표현식
      i*i
      #반복문
      for i in range(1, 10+1)
      #조건문
    ]
    print(l)
    >>>
    [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

     

    리스트 내포의 []를 ()로 바꾸면 제너레이터 표현식이 된다!

    ge = (
      i*i 
      for i in range(1, 10+1))
    print(ge)
    >>>
    <generator object <genexpr> at 0x799a54846730>

     

    참고로,

    제너레이터 표현식은 실제로 값을 생성하기 위해 for 루프나 다른 반복 구조에서 사용해야 함. print(even_squares)를 호출하면 제너레이터 객체의 정보만 출력되고, 실제 요소들은 생성되지 않는다. 제너레이터 객체에서 첫 번째 값을 직접 가져오고 싶다면 next() 함수를 사용한다. 주의할 점은, 제너레이터에서 모든 값을 소비하면(다음 값이 없을 때까지 next()를 호출하면) StopIteration 예외가 발생하게 된다.

     

    이터레이터는 next()라는 함수의 매개변수에 넣어서 내부의 요소를 하나씩 호출할 수 있다.
    제너레이터에서 모든 값을 소비하면(다음 값이 없을 때까지 next()를 호출하면) StopIteration 예외가 발생하게 된다.

    ge = (
      i*i 
      for i in range(1, 4+1))
    print(next(ge))
    print(next(ge))
    print(next(ge))
    print(next(ge))
    print(next(ge))
    >>>
    1
    4
    9
    16
    Traceback (most recent call last):
      File "/home/runner/iteoeojjeogu/main.py", line 20, in <module>
        print(next(ge))
    StopIteration

     

    이터레이터는 이터러블을 만드는 한 가지 종류이기 때문에 for 반복문 뒤에 넣을 수 있다.

    ge = (
      i*i 
      for i in range(1, 10+1)
    )
    for yoso in ge:
      print(yoso)
     >>>
    1
    4
    9
    16
    25
    36
    49
    64
    81
    100

     

    이터레이터를 만드는 방법

    - 제너레이터 함수 사용

     

    #제너레이터 함수

    :함수 내부에 yield 키워드를 사용하면 해당 함수는 제너레이터 함수가 된다.

    제너레이터 함수는 호출했을 때 내부의 코드가 즉시 실행되지 않고 제너레이터를 리턴한다.

    제너레이터는 이터레이터는 next()라는 함수를 이용해서 내부의 요소를 꺼낼 수 있다. 

    def my_generator():
      yield 1
      yield 2
      yield 3
    
    gen = my_generator()
    
    print(next(gen))  # 1 출력
    print(next(gen))  # 2 출력
    print(next(gen))  # 3 출력
    >>>
    1
    2
    3

     

    추가 설명

    더보기
    ChatGPT said...
     

    제너레이터 함수에서 yield 키워드는 함수를 일시 중단하고 값을 반환하는 데 사용됩니다. 이 때 함수는 그 상태를 유지하며 호출자에게 값을 제공하고, 다음에 호출될 때는 마지막으로 멈춘 곳에서 실행을 다시 시작합니다. 이는 함수를 이어서 실행할 수 있게 해주는 독특한 방식입니다.

    구체적으로 yield가 하는 역할은 다음과 같습니다:

    1. 값 반환: yield는 함수가 값을 반환하고 현재 상태를 보존합니다. 일반적인 return 문과는 달리, 함수가 종료되지 않고 호출자에게 제어를 반환합니다.
    2. 일시 중단 및 재개: 함수가 yield를 만나면 일시 중단되고, 호출자는 해당 값에 접근할 수 있습니다. 호출자가 다음 값을 요청하면 함수는 yield가 있는 곳부터 다시 시작하여 다음 값을 생성하고 반환합니다.
    3. 반복 가능한 객체: 제너레이터 함수에 yield가 포함되면 함수는 제너레이터 객체를 반환합니다. 이 객체는 next() 함수로 값을 하나씩 요청받을 수 있는 반복 가능한 객체입니다.

    위 예제에서 my_generator() 함수는 제너레이터 함수입니다. yield를 통해 순차적으로 1, 2, 3을 반환하고 있습니다. 함수는 호출자가 next()를 호출할 때마다 실행을 재개하고 다음 yield에서 멈추게 됩니다.

    따라서 yield는 제너레이터 함수가 값을 생성하는 주요 메커니즘입니다. 이를 통해 메모리를 효율적으로 사용하며, 큰 데이터 집합을 처리할 때 유용한 반복 가능한 객체를 생성할 수 있습니다.

    그래서 처음의 1부터 10까지의 정수를 제곱하는 프로그램을 제너레이터 함수로 만들면

    def power_generator():
     for i in range(1, 10+1):
       yield i*i
    
    pg = power_generator()
    
    print(next(pg))
    print(next(pg))
    print(next(pg))  
    print(next(pg))
    print(next(pg))
    >>>
    1
    4
    9
    16
    25

     

    이터레이터는 이터러블을 만드는 한 가지 종류이기 때문에 for 반복문 뒤에 넣을 수 있다. 라고 했으니까..

    def power_generator():
     for i in range(1, 10+1):
       yield i*i
    
    pg = power_generator()
    
    for yoso in pg:
      print(yoso)
    >>>
    1
    4
    9
    16
    25
    36
    49
    64
    81
    100

     

    # 리스트 내포 대신 제너레이터를 쓰는 이유

    : 메모리 효율성)  리스트 내포는 한 번에 모든 결과를 리스트로 만들어 메모리에 저장하기 때문에 CPU와 메모리 등의 자원을 많이 차지한다. 이에 반해 제너레이터는 값을 한 번에 모두 생성하지 않고, 필요할 때마다 하나씩 생성한다. 해당 코드를 실행하는 순간 기존의 데이터를 사용하고 특정 요소를 사용할 때 표현식 연산을 하기 때문에 연산이 분산된다.

     


    https://replit.com/@wh3308/iteoeojjeogu

Designed by Tistory.