У вас есть два варианта:
Либо используйте цикл while True:
и выходите, когда следующий блок пуст:
def generator(datasource):
while True:
data_chunk = get_data_chunk(datasource)
if not data_chunk:
return
for item in data_chunk:
yield item
Используйте форму с двумя аргументами функции iter()
в цикле for
:
def generator(datasource):
for data_chunk in iter(lambda: get_data_chunk(datasource), None):
for item in data_chunk:
yield item
или, используя itertools.chain.from_iterable()
:
from itertools import chain
def generator(datasource):
chunk_iter = iter(lambda: get_data_chunk(datasource), None)
yield from chain.from_iterable(chunk_iter)
Последнее требует, чтобы вы знали, как выглядит «конечное значение». Выше я предполагал, что это конечное значение равно None
, но если это пустой список, вам нужно заменить None
на []
.
Демо-версия:
>>> from itertools import chain, islice
>>> from random import randrange
>>> demosource = (randrange(11, 81) for _ in range(17))
>>> def get_data_chunk(datasource, chunksize=10):
... return list(islice(datasource, chunksize))
...
>>> def generator(datasource):
... chunk_iter = iter(lambda: get_data_chunk(datasource), []) # last chuck is an empty list
... yield from chain.from_iterable(chunk_iter)
...
>>> list(generator(demosource))
[38, 47, 74, 13, 23, 24, 47, 61, 30, 38, 70, 41, 43, 47, 37, 34, 67]