2.30. Включення¶
Включення (comprehension) будує новий список, множину, словник або генератор з існуючого ітерованого об’єкта в одному виразі. Це заміна поширеного шаблону, коли починають з порожнього контейнера та додають елементи в циклі.
2.30.1. Включення списків¶
squares = [x * x for x in range(5)]
print(squares)
Виведення:
[0, 1, 4, 9, 16]
Той самий цикл у розгорнутому вигляді:
squares = []
for x in range(5):
squares.append(x * x)
Форма включення є одним виразом, що будує список на місці. Немає squares = [] і немає .append – результатом є значення самого включення.
Провідний вираз породжує кожен елемент; оператор for визначає змінну циклу; необов’язковий if фільтрує елементи.¶
2.30.2. Фільтрація за допомогою if¶
Необов’язковий оператор if залишає лише елементи, що відповідають умові:
evens = [x for x in range(10) if x % 2 == 0]
print(evens)
Виведення:
[0, 2, 4, 6, 8]
Фільтр виконується перед провідним виразом – спочатку перевіряється x % 2 == 0; лише відповідні значення потрапляють до x у виведенні.
2.30.3. Включення словників та множин¶
Та сама структура працює зі словниковими та множинними літералами.
Включення словника має пару key: value перед for:
squares = {x: x * x for x in range(5)}
print(squares)
Виведення:
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
Включення множини використовує фігурні дужки та один вираз:
unique_lengths = {len(w) for w in ["a", "bb", "c", "bb"]}
print(unique_lengths)
Виведення:
{1, 2}
2.30.4. Генераторні вирази¶
Круглі дужки породжують генераторний вираз замість списку. Значення обчислюються по одному, на вимогу:
total = sum(x * x for x in range(1000))
Список з мільйона елементів ніколи не будується. Значення надходять по одному до sum(), який додає їх і відкидає кожне по мірі обробки.
Генераторні вирази є правильним вибором при передачі значень до функції-редуктора (sum(), max(), any(), all()) або будь-якого іншого коду, що споживає ітератор – вони економлять пам’ять, яку зайняв би еквівалентний список.
2.30.5. Коли не варто використовувати включення¶
Включення є лаконічними, але не завжди більш зрозумілими. Використовуйте звичайний цикл for, коли:
Тіло потребує більше одного оператора (включення вміщує рівно один вираз).
Тіло має побічні ефекти (виведення, запис у файл) – включення призначені для побудови колекції, а не для виконання дій.
Фільтр або перетворення мають так багато частин, що включення більше не читається зліва направо.