2.30. Comprehensions

Comprehension sestaví nový list, set, dict nebo generátor z existujícího iterovatelného objektu v jediném výrazu. Je náhradou za běžný vzor, kdy začnete prázdným kontejnerem a v cyklu do něj přidáváte prvky.

2.30.1. List comprehensions

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

Výstup:

[0, 1, 4, 9, 16]

Tentýž cyklus rozepsaný:

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

Forma comprehension je jediný výraz, který sestaví list rovnou na místě. Není zde žádné squares = [] ani žádné .append – výsledkem je hodnota dané comprehension.

Výraz „[f(x) for x in xs if cond]“ s popisky: úvodní výraz je výsledek, klauzule for pojmenovává řídicí proměnnou cyklu, klauzule if filtruje, které prvky zůstanou zachovány.

Úvodní výraz produkuje každý prvek; klauzule for pojmenovává řídicí proměnnou cyklu; volitelná klauzule if prvky odfiltrovává.

2.30.2. Filtrování pomocí if

Volitelná klauzule if zachová pouze prvky, které vyhovují:

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

Výstup:

[0, 2, 4, 6, 8]

Filtr běží před úvodním výrazem – nejprve se ověří x % 2 == 0; do x se pro výstup dostanou pouze vyhovující hodnoty.

2.30.3. Dict a set comprehensions

Tentýž tvar funguje i s literály dict a set.

Dict comprehension má před for dvojici key: value:

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

Výstup:

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

Set comprehension používá složené závorky a jediný výraz:

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

Výstup:

{1, 2}

2.30.4. Generátorové výrazy

Kulaté závorky produkují místo listu generátorový výraz. Hodnoty se počítají po jedné, na vyžádání:

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

Žádný milionprvkový list se nikdy nevytvoří. Hodnoty proudí jedna po druhé do sum(), která je sčítá a každou postupně zahazuje.

Generátorové výrazy jsou správnou volbou při předávání hodnot do redukční funkce (sum(), max(), any(), all()) nebo do jakéhokoli jiného kódu konzumujícího iterátory – ušetří paměť, kterou by spotřeboval ekvivalentní list.

2.30.5. Kdy comprehension nepoužít

Comprehensions jsou stručné, ale ne vždy přehlednější. Po prostém cyklu for sáhněte, když:

  • Tělo potřebuje více než jeden příkaz (do comprehension se vejde přesně jeden výraz).

  • Tělo má vedlejší účinky (tisk, zápis do souboru) – comprehensions slouží k sestavení kolekce, nikoli ke spouštění akcí.

  • Filtr nebo transformace mají tolik částí, že se comprehension už nečte zleva doprava.