.. _gen: Generatori/iteratori ======================== Generatorske funkcije -------------------------- Spomenuli smo da ``for`` petlja može "ići" ne samo po elementima liste (ili drugih *sequence* tipova) nego po bilo kojem *iteratoru*. *Iteratori* su objekti koji definiraju niz omogućavanjem dohvaćanja sljedećeg elementa iz niza. Time se definira niz jer se ponavljanjem te radnje prođu tj. dohvate svi elementi niza. Iterator dakle pamti koliko elemenata je već prošao te sadrži recept kako dobiti sljedeći element. Pisanje općenitog iteratora obično nije praktično. Jednostavnije je koristiti *generatorske funkcije*. Za razliku od običnih funkcija koje vraćaju jednu vrijednost (koja može biti lista ili ``tuple``) generatorske funkcije vraćaju više vrijednosti koristeći princip iteratora. Sama generatorska funkcija izgleda isto kao obična osim što u sebi sadrži naredbu :keyword:`yield`. ``yield`` dohvaća sljedeću od više vrijednosti koje generatorska funkcija vraća. Ona je slična naredbi ``return`` jer kao i ``return`` izlazi van funkcije i vrati vrijednost. Međutim, kad se zatraži sljedeća vrijednost, generatorske funkcije će se nastaviti izvršavati dalje (a ne od početka) do sljedeće naredbe ``yield``. Pogledajmo primjere: .. literalinclude:: gen1.py :language: python .. literalinclude:: gen1.py.filtered :language: text Nakon što pozivatelj zatraži sljedeću vrijednost funkcija se izvršava do naredbe ``yield``. Kad pozivatelj ponovno zatraži sljedeću vrijednost, izvršavanje funkcije se **nastavlja** od naredbe koja slijedi prethodnoj naredbi ``yield`` do sljedeće ``yield``. Ako pozivatelj zatraži sljedeću vrijednost a izvršavanje funkcije dođe do kraja ili do naredbe ``return`` to izazove grešku ``StopIteration``. Ta greška služi kao oznaka pozivatelju da nema više vrijednosti koje funkcija treba vratiti. Obično je pozivatelj petlja: .. literalinclude:: gen2.py :language: python .. literalinclude:: gen2.py.filtered :language: text U gornjem primjeru petlja interno obrađuje grešku tako da nam ovdje detalji obrade pogrešaka nisu bitni. Nešto više detalja o ``try/except`` je dano u :ref:`exc`. *Generator comprehensions* ---------------------------------- Ako se ``for .. in`` stavi u uglate zagrade rezultat je lista. .. literalinclude:: gen3a.py :language: python .. literalinclude:: gen3a.py.filtered :language: text Ako se ``for .. in`` stavi u okrugle zagrade rezultat je iterator. .. literalinclude:: gen3.py :language: python .. literalinclude:: gen3.py.filtered :language: text Pogledati primjere u odjeljku :ref:`z1z3b`. Više na: - https://docs.python.org/3/glossary.html#index-20 - https://djangostars.com/blog/list-comprehensions-and-generator-expressions/ Pretvaranje liste u iterator ---------------------------------- Koristeći :func:`iter` možemo prebaciti razne tipove u iterator npr. liste: .. literalinclude:: gen4.py :language: python .. literalinclude:: gen4.py.filtered :language: text Pretvaranje iteratora u listu --------------------------------- Koristeći :func:`list` možemo prebaciti razne tipove u listu npr. iteratore: .. literalinclude:: gen5.py :language: python .. literalinclude:: gen5.py.filtered :language: text .. _gen_pridr: Pridruživanje iteratora varijablama --------------------------------------- Može biti koristan i ovaj način pozivanja generatorskih funkcija: .. literalinclude:: gen6.py :language: python .. literalinclude:: gen6.py.filtered :language: text