Python 3/Generaattorifunktiot


Generaattorifunktioksi sanotaan funktiota, joka palauttaa generaattorinolion. Kun next-funktiota kutsutaan palautetulla generaattorioliolla, palauttaa se aina uuden arvon. Tällaista oliota vi käyttää for-silmukassa iteraattorina, sillä for kutsuu sisäisesti nextfunktiota oliolle. Generaattori voi palauttaa loputtomasti uusia arvoja tai se voi palauttaa niitä tietyn määrän. Arvot lasketaan vasta niitä pyydettäessä ns. laiskasti.

Generaattorifunktio toimii siten, että siitä palautetaan arvo yield-komennolla. Funktion suoritus keskeytetään tähän kohtaan. Seuraavalla next-komennolla suoritusta jatketaan kohdan jälkeen. Generaattorin suoritus loppuu, kun päästään funktion loppuun tai siitä palataan return-sanalla.

Esimerkiksi muutamme for-silmukkaa käsittelevässä osassa olevan, kymmenen ensimmäistä Fibonaccin lukua laskevan silmukan luvut yksi kerrallaan palauttavaksi generaattorifunktioksi.

def fibonacci(max_n):
    a = 1
    b = 1
    for _ in range(0, max_n):
        yield a  # a palautetaan
        n = a + b
        a = b
        b = n

Aina kun for-silmukassa tullaan yield-komentoon, palautetaan a. Seuraavalla kerralla suoritus jatkuu yield-komennon jälkeisestä rivistä.

Nyt muussa koodissa voidaan käydä läpi haluttu määrä Fibonaccin lukuja yksinkertaisesti.

for num in fibonacci(10):
    print(num)

Rajaton generaattorifunktio muokkaa

Koska generaattorifunktio laskee seuraavan arvon vasta sitä tarvittaessa, voidaan niitä käyttää hvyin silloin, kun yläraja ei ole etukäteen tiedossa. Silloin kutsuvassa koodissa pitää olla jokin lopetusehto. Muuten ohjelma ei pääty koskaan.

Fibonaccin lukuja generoiva funktio voitaisiin muuttaa ylärajattomaksi tekemällä silmukasta ikuinen silmukka.

def fibonacci4ever():
    a = 1
    b = 1
    while True:
        yield a
        n = a + b
        a = b
        b = n

Nyt kutsuva koodi voisi esimerkiksi tulostaa kaikki 500 pienemmät Fibonaccin luvut.

for num in fibonacci4ever():
    if num > 500:
        break
    print(num)