Zadanie
Na podstawie generatora do generowania kolejnych liczb naturalnych napisz nowy generator zwracający listę N kolejnych liczb z tego ciągu.
Generator liczb naturalnych
Generator liczb naturalnych zwraca liczby: 1,2,3,4,5,6,7,8,9 …
Natomiast nasz generator ma zwarć listy kolejnych N elementów czyli: [1,2,3] [4,5,6] [7,8,9] dla N równego 3.
def gen_liczb_naturalnych(): a = 0 while True: a += 1 yield a
Szybkie przypomnienie jak to działa. Każde kolejne wywołanie tego generatora spowoduje:
- zwrócenie wartości znajdującej się po słowie kluczowym yield
- zatrzymanie całej funkcji na tej linii
- zapisanie wszystkich zmiennych używanych w generatorze by móc je odtworzyć przy kolejnym wywołaniu generatora
Dzięki temu każde kolejne wywołanie generatora zwróci następną liczbę naturalną.
Rozwiązanie
W języku Python nie ma żadnego problemu by jeden generator wywoływał inny. W naszym przypadku raz wywołany generator list liczb naturalnych wywoła N razy zwykły generator liczb naturalnych.
Zatem nasz generator musi używać generatora liczb naturalnych aby zebrać zadaną ilość wartości i zwrócić jako listę. Zobaczmy jak by to wyglądało na diagramie.
Ja wyobrażam sobie to jako tryby w zegarze. Jeden obrócenie się większego trybu powoduje trzykrotne obrócenie mniejszego. Czyli jedno zapytanie generatora powoduje trzykrotne wywołanie drugiego. Potem wszystkie zmienne są zapisywanie w pamięci i czekają na kolejne zapytanie generatora list naturalnych. I tak bez końca :). Kod naszego generatora wygląda następująco:
def gen_liczb_naturalnych(): a = 0 while True: a += 1 yield a def gen_list_liczb_naturalnych(n): liczby_naturalne = gen_liczb_naturalnych() lista = [] while True: for _ in range(n): lista.append(next(liczby_naturalne)) yield lista lista.clear() listy_liczb_nat = gen_list_liczb_naturalnych(3) print(next(listy_liczb_nat)) print(next(listy_liczb_nat)) print(next(listy_liczb_nat))
Output:
[1, 2, 3] [4, 5, 6] [7, 8, 9]
Możliwość łączenia ze sobą generatorów jest bardzo pomocna. Tego typu mechanizm można zastosować na przykład do pobierania określonej porcji danych do przetworzenia. Przykładowo mając generator czytający linie po linii można stworzyć drugi czytający te ta dane strona po stronie. Generatory takie działają bardzo szybko i raczej nie powodują spowolnienia naszego programu. Na dzisiaj tyle. Do tematu generatorów na pewno jeszcze wrócimy.