Generátorok és a yield kulcsszó
A generátor egy olyan speciális függvény, amely egymás után több értéket is vissza tud adni, és a futását menet közben "szüneteltethetjük", majd "folytathatjuk". Egy generátor kódja "ránézésre" annyiban tér el egy függvényétől, hogy a return kulcsszó helyett a yield kulcsszót használjuk az értékek visszaadására.
Míg a return kulcsszó visszaad egy értéket, és utána megszakítja a függvényt (tehát a kód maradéka már nem fut le), addig a yield miután visszaadta az értéket, a függvényünket egyszerűen "hibernálja" - azaz a kód nem fut tovább, de a Python megjegyzi, hogy éppen hol tartott a függvény végrehajtásával, mik voltak ekkor a változókban, stb., és amikor legközelebb újra meghívjuk ugyanezt a generátort, akkor a kód futása onnan folytatódik, ahol legutóbb az előző yield-nél abbahagytuk, és fut tovább a következő yield-ig, vagy a kód végéig.
Nézzünk tehát egy rövid példát a return és a yield közti különbség megértéséhez
| Függvény return-nel | Függvény yield-el |
|---|---|
|
|
Első szám: 1 Második szám: 1 Harmadik szám: 1 |
Első szám: 1 Második szám: 2 Harmadik szám: 3 |
A return kulcsszót használó függvény esetén az érték mindhárom függvényhívás esetén 1 lesz. Ezzel szemben a yield-et használó generátor esetén a kód onnan folytatódik, ahol a legutóbbi futáskor abbamaradt, így a három egymást követő meghíváskor három különböző értéket kapunk.
A generátorokat használhatjuk for ciklusokban is, így egy for ciklus segítségével megkaphatjuk egy generátor összes értékét. Ha például készítünk egy generátort, ami megkeresi egy szám osztóit, akkor a generátort egy for ciklusba helyezve végiglépkedhetünk azokon:
def osztoi(szam):
for oszto in range(1, szam+1):
if szam % oszto == 0:
yield oszto
for szam in osztoi(24):
print(szam)
Persze ez csak akkor jó megoldás, ha a generátorunk nem generál végtelenül sok számot -- ez esetben ugyanis könnyen végtelen ciklusba juthatunk. Ha egy generátor "kimerült", azaz eljutott a kódja végére, és nincs több yield utasítás, akkor a következő futtatáskor "előről" fog indulni.
Amennyiben a fentebbi példához hasonlóan olyan generátort készítünk, aminek vannak paraméterei (mint ebben a példában a szám, aminek az osztóit keressük), akkor ha a generátort ugyanazzal a paraméterrel hívjuk meg újra és újra, akkor folytatódik a futása, ha viszont egy másik paramétert adunk meg neki, akkor egy új példány indul el belőle. Így egy generátornak több különböző példánya is "várakozhat" egyszerre különböző "állapotban".
Generátorok tárolása változókban
Hamarosan!