2.30. Comprehension kifejezések

Egy comprehension egy új listát, halmazt, szótárt vagy generátort épít fel egy meglévő iterálható objektumból, egyetlen kifejezésben. Helyettesíti azt a gyakori mintát, amikor egy üres tárolóból indulsz, és egy ciklusban hozzáfűzöl elemeket.

2.30.1. Lista comprehension kifejezések

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

Kimenet:

[0, 1, 4, 9, 16]

Ugyanaz a ciklus kiírva:

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

A comprehension forma egyetlen kifejezés, amely helyben építi fel a listát. Nincs squares = [] és nincs .append – az eredmény maga a comprehension értéke.

A "[f(x) for x in xs if cond]" kifejezés magyarázattal: a vezető kifejezés az eredmény, a for tagmondat megnevezi a ciklusváltozót, az if tagmondat szűri, hogy mely elemek maradjanak meg.

A vezető kifejezés állítja elő az egyes elemeket; a for tagmondat megnevezi a ciklusváltozót; egy opcionális if szűri ki az elemeket.

2.30.2. Szűrés if használatával

Egy opcionális if tagmondat csak az illeszkedő elemeket tartja meg:

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

Kimenet:

[0, 2, 4, 6, 8]

A szűrő a vezető kifejezés előtt fut le – az x % 2 == 0 ellenőrzése történik először; csak az illeszkedő értékek jutnak el az x változóhoz a kimenethez.

2.30.3. Szótár- és halmaz-comprehension kifejezések

Ugyanaz az alak működik szótár- és halmazliterálokkal is.

Egy szótár-comprehension egy key: value párt tartalmaz a for előtt:

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

Kimenet:

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

Egy halmaz-comprehension kapcsos zárójeleket és egyetlen kifejezést használ:

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

Kimenet:

{1, 2}

2.30.4. Generátorkifejezések

A kerek zárójelek lista helyett egy generátorkifejezést állítanak elő. Az értékek egyenként, igény szerint számítódnak ki:

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

Soha nem épül fel egymilliós elemű lista. Az értékek egyesével áramlanak a sum() függvénybe, amely összeadja őket, és menet közben mindegyiket eldobja.

A generátorkifejezések a megfelelő választás, amikor egy redukáló függvénybe (sum(), max(), any(), all()) vagy bármely más iterátort fogyasztó kódba táplálsz értékeket – megspórolják azt a memóriát, amelyet az egyenértékű lista használt volna.

2.30.5. Mikor ne használj comprehension kifejezést

A comprehension kifejezések tömörek, de nem mindig világosabbak. Nyúlj egy egyszerű for ciklushoz, amikor:

  • A törzsnek egynél több utasításra van szüksége (egy comprehension pontosan egyetlen kifejezésbe fér bele).

  • A törzsnek mellékhatásai vannak (kiírás, fájlba írás) – a comprehension kifejezések egy gyűjtemény felépítésére valók, nem műveletek futtatására.

  • A szűrő vagy az átalakítás annyi részből áll, hogy a comprehension már nem olvasható balról jobbra.