Dev./Python.

[Python] Generator와 핵심 yield 키워드

devz0 2023. 4. 26. 00:11
728x90
반응형

 

Generator

Generator는 Iterator(값을 차례대로 꺼낼 수 있는 객체)를 만들어주는 함수이다. Generator는 Iterator를 생성해주기 때문에, 한번에 모든 값을 메모리에 저장하지 않아도 된다. 대신 값을 생성하는 시점에서 값을 생성하고 바로 반환하며, 다음 값이 필요한 시점에서 다시 실행된다. 이런 동작원리로 메모리를 효율적으로 사용할 수 있다.

 

특징

generator 함수는 일반 함수와 유사하지만, return 대신 yield 구문을 사용하여 값을 반환하고, 함수를 호출할 때마다 generator 객체를 반환한다. generator 객체는 iterator protocol을 구현하여, next() 함수를 호출하면 generator 함수에서 yield 구문에서 반환한 값을 하나씩 가져올 수 있다. 

 

참조 페이지에서 예제를 가져왔다.

names = ['Alice', 'Bob', 'Chris', 'David', 'Emily']

 

이 리스트로 부터 제너레이터를 정의하면

 

 def gen_roster(names):
     for name in names:
         yield name
         
 roster = gen_roster(names)

 

제너레이터에서는 return 대신 yield키워드를 사용해야 한다. 

 

In [5]: roster
Out[5]: <generator object gen_roster at 0x7fb76cfda270>

roster의 결과를 확인하면 genenator 객체가 찍힌다. 반복가능한 객체이므로 반복문을 사용해 이름을 하나씩 뽑을 수 있다.

 

 

yield 

yield는 함수가 실행 중에 값을 반환하고, 함수의 실행 상태를 저장

yield는 generator 함수를 정의할 때 사용되는 키워드이다. yield 구문은 generator 함수의 실행을 일시 중지하고, 해당 함수가 생성한 값을 호출자(caller)에게 반환한다. 그리고 함수의 상태를 보존한 채로 일시 중지된 지점에서 다시 실행이 가능하다. 즉, yield는 함수가 값을 반환하면서도 실행 상태를 유지하는 기능을 한다. yield 키워드를 사용하면 generator 함수에서 값을 하나씩 반환할 수 있으며,generator 객체는 이러한 값을 순서대로 생성하여 반환한다. next() 함수를 사용하여 generator 객체의 다음 값을 가져올 수 있다.

 

In [6]: roster.__next__()
Out[6]: '앨리스'

In [7]: roster.__next__()
Out[7]: '밥'

In [8]: roster.__next__()
Out[8]: '크리스'

In [9]: roster.__next__()
Out[9]: '데이빗'

In [10]: roster.__next__()
Out[10]: '에밀리'

In [11]: roster.__next__()
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
Cell In[11], line 1
----> 1 roster.__next__()

StopIteration:

예시로 만든 제너레이터 객체에 next() 함수를 사용하면 하나씩 이동된 값이 출력된다. 위에서 본 정의처럼 함수의 상태를 보존한 채로 다음 함수를 호출하면 일시 중지된 지점에서 다시 실행해 다음 값을 반환해준다. 리스트 마지막 객체 출력 이후 함수를 또 호출하면 더이상 없기 때문에 오류가 발생한다.

 

 

어떻게 활용할 수 있을 까?

나는 사내 서비스를 구독형 모델로 새롭게 만들고 있는데 PostgreSQL RLS 활성화시 데이터베이스 ROLE을 SET / RESET해줄 때 사용했다. with 구문을 사용해 SQL 문들을 커서를 통해 실행하여 데이터베이스에 접근해 ROLE을 SET 해준후 yield 키워드를 작성해 yield 키워드가 실행되면, 함수가 Generator 객체를 반환하고 현재 함수의 실행 상태를 유지하도록 했다.  with 구문이 종료되면 커서 객체도 자동으로 닫히고, 마지막으로 SQL 문들을 실행하여 설정한 값들이 초기화 되도록 yield 키워드 이후 RESET ROLE문을 작성했다.

    -> 초기화 시킨 이유는 커넥션 객체가 유지되는 동안 설정한 값들이 다음에 실행될 SQL 문에 영향을 미치는 것을 방지하기 위함이다.

 

 

 

 

 

 

 

 

참조

728x90
반응형