2.30. Lyhennetyt muodostimet

Lyhennetty muodostin rakentaa uuden listan, joukon, sanakirjan tai generaattorin olemassa olevasta iteroitavasta yhdellä lausekkeella. Se korvaa yleisen mallin, jossa aloitetaan tyhjästä säiliöstä ja lisätään alkioita silmukassa.

2.30.1. Listamuodostimet

squares = [x * x for x in range(5)]
print(squares)

Tuloste:

[0, 1, 4, 9, 16]

Sama silmukka auki kirjoitettuna:

squares = []
for x in range(5):
    squares.append(x * x)

Muodostinmuoto on yksi lauseke, joka rakentaa listan paikallaan. Ei ole squares = []-riviä eikä .append-kutsua – tulos on muodostimen arvo.

Lauseke "[f(x) for x in xs if cond]" selitettynä: alkupään lauseke on tulos, for-lause nimeää silmukkamuuttujan, if-lause suodattaa, mitkä alkiot säilytetään.

Alkupään lauseke tuottaa jokaisen alkion; for-lause nimeää silmukkamuuttujan; valinnainen if suodattaa alkioita pois.

2.30.2. Suodatus if-lauseella

Valinnainen if-lause säilyttää vain alkiot, jotka täsmäävät:

evens = [x for x in range(10) if x % 2 == 0]
print(evens)

Tuloste:

[0, 2, 4, 6, 8]

Suodatin suoritetaan ennen alkupään lauseketta – x % 2 == 0 tarkistetaan ensin; vain täsmäävät arvot päätyvät muuttujaan x tulostetta varten.

2.30.3. Sanakirja- ja joukkomuodostimet

Sama muoto toimii sanakirja- ja joukkoliteraalien kanssa.

Sanakirjamuodostimessa on key: value -pari ennen for-osaa:

squares = {x: x * x for x in range(5)}
print(squares)

Tuloste:

{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Joukkomuodostin käyttää aaltosulkeita ja yhtä lauseketta:

unique_lengths = {len(w) for w in ["a", "bb", "c", "bb"]}
print(unique_lengths)

Tuloste:

{1, 2}

2.30.4. Generaattorilausekkeet

Tavalliset sulkeet tuottavat generaattorilausekkeen listan sijaan. Arvot lasketaan yksi kerrallaan tarpeen mukaan:

total = sum(x * x for x in range(1000))

Miljoonan alkion listaa ei koskaan rakenneta. Arvot virtaavat yksitellen sum()-funktioon, joka laskee ne yhteen ja hylkää kunkin sitä mukaa.

Generaattorilausekkeet ovat oikea valinta, kun syötät arvoja pelkistävään funktioon (sum(), max(), any(), all()) tai mihin tahansa muuhun iteraattoria kuluttavaan koodiin – ne säästävät muistin, jonka vastaava lista olisi käyttänyt.

2.30.5. Milloin lyhennettyä muodostinta ei kannata käyttää

Muodostimet ovat tiiviitä mutta eivät aina selkeämpiä. Tartu tavalliseen for-silmukkaan kun:

  • Runko tarvitsee enemmän kuin yhden lauseen (muodostimeen mahtuu täsmälleen yksi lauseke).

  • Rungolla on sivuvaikutuksia (tulostus, tiedostoon kirjoittaminen) – muodostimet ovat kokoelman rakentamista varten, eivät toimintojen suorittamista varten.

  • Suodattimessa tai muunnoksessa on niin monta osaa, ettei muodostin enää luetu vasemmalta oikealle.