python에서 제너레이터(Generator)를 생성할 때 사용되는 키워드
제너레이터는 반복 가능한 객체(iterable)을 만들어 주는데, 값을 하나씩 생성해서 반환하고 그 상태를 기억해 함수의 실행을 일시 중단 할 수 있다. 이를 통해 메모리를 효율적으로 사용한다.
'yield' 를 사용한 함수는 호출될 때 제너레이터 객체를 반환한다.
이 객체는 실제로 함수 내의 코드를 실행하지 않는다. 대신에 값을 필요할 때마다 호출자에게 반환한다.
함수의 실행은 'yield'에서 일시 중단되고, 호출자가 다음 값을 요청하면 다시 시작된다.
예를 들자면 0에서 시작해 무한히 증가하는 제너레이터를 만드는 함수 코드이다.
def infinite_generator():
i = 0
while True:
yield i
i +=1
# 제너레이터 객체 생성
generator_obj = infinite_generator()
print(next(generator_obj)) #output 0
print(next(generator_obj)) #output 1
print(next(generator_obj)) $output 2
즉 위 코드에서 보듯이, yield i 는 현재 값을 반환하고 함수의 실행을 일시 중단한다.
그리고 next()
함수를 사용해 호출자는 제너레이터로부터 값을 요청하고, 함수의 실행이 중단된 지점에서 다시 시작하여 다음 값을 반환한다.
0부터 시작해서 주어진 limit 까지 짝수를 생성하는 제너레이터를 만든다면,
def generator_even_numbers(limit):
i = 0
while i <= limit:
if i%2==0:
yield i
i+=1
even_generator = generator_even_numbers(10)
for number in even_generator:
print(number)
yield i 는 현재 짝수를 반환하고 함수의 실행을 일시 중지한다.
호출자는 for 루프를 사용해 제너레이터로부터 값을 요청하면, 함수의 실행이 중단된 지점에서 다시 시작되어 다음 짝수를 생성하고 반환한다.
-> 이러한 방식으로 'yield'를 사용하면 대용량 데이터셋을 메모리에 모두 로드하지 않고 필요한 만큼만 생성하여 사용할 수 있다.
def read_large_file(file_path):
with open(file_path, 'r') as file:
for line in file:
yield line.strip()
# 파일에서 데이터를 읽어오는 제너레이터 객체 생성
log_reader = read_large_file('large_log_file.txt')
# 호출자에게 값을 하나씩 반환
for line in log_readers:
print(line)
예를 들어 'asyncio' 라이브러리를 사용해서 비동기적으로 웹 페이지를 가져온다고 가정한다면
import aiohttp
import asyncio
async def fetch_url(url):
async with aiohttp.ClinetSession() as session:
async with sessionn.get(url) as response:
return await response.text()
async def async_data_generator(urls):
for url in urls:
data = await fetch_url(url)
yield data
# 비동기 작업을 위한 루프
async def main():
urls = ['http://example.com', 'http://example.org', 'http://example.net']
async for data in async_data_generator(urls):
print(data)
# 이벤트 루프 실행
asyncio.run(main())
위에서 'fetch_url'은 비동기적으로 주어진 url에서 데이터를 가져오는 역할이다.
'asynco_data_generator' 함수는 여러 url에 대해 'fetch_url' 함수를 호출하고 가져온 데이터를 제러네이터를 통해 반환한다.
main 함수에서 'asynco_data_generator'를 비동기적으로 호출하고 가져온 데이터를 출력하고 있다.
위와 같이 'yield'와 비동기 작업을 결합하면 여러 비동기적인 이벤트나 작업을 효율적으로 처리할 수 있다.