2.30. Wyrażenia listowe (comprehensions)¶
Wyrażenie składane (comprehension) buduje nową listę, zbiór, słownik lub generator z istniejącego obiektu iterowalnego w pojedynczym wyrażeniu. Zastępuje powszechny wzorzec polegający na rozpoczęciu od pustego kontenera i dołączaniu elementów w pętli.
2.30.1. Wyrażenia listowe¶
squares = [x * x for x in range(5)]
print(squares)
Wynik:
[0, 1, 4, 9, 16]
Ta sama pętla zapisana w pełnej formie:
squares = []
for x in range(5):
squares.append(x * x)
Forma wyrażenia składanego to jedno wyrażenie, które buduje listę w miejscu. Nie ma squares = [] ani .append – wynikiem jest wartość wyrażenia składanego.
Wiodące wyrażenie wytwarza każdy element; klauzula for nazywa zmienną pętli; opcjonalna klauzula if odfiltrowuje elementy.¶
2.30.2. Filtrowanie za pomocą if¶
Opcjonalna klauzula if zachowuje tylko pasujące elementy:
evens = [x for x in range(10) if x % 2 == 0]
print(evens)
Wynik:
[0, 2, 4, 6, 8]
Filtr działa przed wiodącym wyrażeniem – najpierw sprawdzane jest x % 2 == 0; tylko pasujące wartości trafiają do x dla wyniku.
2.30.3. Wyrażenia słownikowe i zbiorów¶
Ten sam kształt działa z literałami słownika i zbioru.
Wyrażenie słownikowe ma parę key: value przed klauzulą for:
squares = {x: x * x for x in range(5)}
print(squares)
Wynik:
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
Wyrażenie zbioru używa nawiasów klamrowych i pojedynczego wyrażenia:
unique_lengths = {len(w) for w in ["a", "bb", "c", "bb"]}
print(unique_lengths)
Wynik:
{1, 2}
2.30.4. Wyrażenia generatorowe¶
Nawiasy okrągłe wytwarzają wyrażenie generatorowe zamiast listy. Wartości są obliczane pojedynczo, na żądanie:
total = sum(x * x for x in range(1000))
Lista o milionie elementów nigdy nie jest budowana. Wartości przepływają jedna po drugiej do sum(), która je dodaje i odrzuca każdą w miarę postępu.
Wyrażenia generatorowe są właściwym wyborem przy podawaniu wartości do funkcji redukującej (sum(), max(), any(), all()) lub do dowolnego innego kodu konsumującego iterator – oszczędzają pamięć, którą zajęłaby równoważna lista.
2.30.5. Kiedy nie używać wyrażenia składanego¶
Wyrażenia składane są zwięzłe, ale nie zawsze bardziej czytelne. Sięgnij po zwykłą pętlę for, gdy:
Ciało wymaga więcej niż jednej instrukcji (wyrażenie składane mieści dokładnie jedno wyrażenie).
Ciało ma efekty uboczne (drukowanie, zapis do pliku) – wyrażenia składane służą do budowania kolekcji, a nie do wykonywania akcji.
Filtr lub przekształcenie ma tak wiele części, że wyrażenie składane przestaje się czytać od lewej do prawej.