Comprehension с условием if: фильтр списка в Python
В новый список часто нужны не все элементы, а только подходящие: чётные числа, дорогие товары, имена на нужную букву. Условие if внутри comprehension фильтрует список одной строкой — а вот if-else делает другое, и путать их нельзя.
Редакция Питоники
Прошлый урок строил списки-близнецы: каждый элемент источника превращался в новый. Но чаще нужен не весь список, а выборка: из оценок — только пятёрки, из цен — только доступные, из слов — только длинные. Это работа фильтра, и comprehension умеет её одной строкой: к конструкции добавляется условие if. Разберём фильтр на знакомой задаче, его место в записи, сложные условия — и вторую роль if, которая живёт в другой части строки и делает совсем другое.
Задача: выбрать чётные
Циклом задача решается уже знакомым шаблоном: приёмник, перебор, условие, append — по строке на каждый шаг:
nums = [4, -2, 7, 5, 8]
evens = []
for n in nums:
if n % 2 == 0:
evens.append(n)
print(evens)
[4, -2, 8]
Четверка, минус двойка и восьмёрка прошли проверку на чётность, семёрка и пятёрка остались за бортом. Шаблон вырос до четырёх строк, и все четыре повторяются в каждой задаче фильтрации на свете — меняются только условие и выражение.
if внутри comprehension
Comprehension сжимает шаблон обратно в одну строку: условие дописывается в конец, после перебора:
nums = [4, -2, 7, 5, 8]
evens = [n for n in nums if n % 2 == 0]
print(evens)
[4, -2, 8]
Результат тот же, а читается строка как фраза: список из n для каждого n в nums, если n делится на два. if в конце comprehension — это фильтр: условие проверяет каждый элемент, и внутрь нового списка попадают только прошедшие проверку. Непрошедшие не заменяются и не обрезаются — они просто не попадают в результат, поэтому длина выборки может быть меньше исходной.
- Выражение — n: что кладётся в новый список прошедшим элементам
- Перебор — for n in nums: откуда берутся элементы
- Фильтр — if n % 2 == 0: условие, которое должно оказаться True, стоит после перебора
Фильтр по строкам
Условием может быть любой вызов, возвращающий True или False. У строк такой проверкой удобно служит startswith — начинается ли слово с префикса:
names = ['анна', 'борис', 'артём', 'вера']
print([name for name in names if name.startswith('а')])
['анна', 'артём']
Анна и Артём прошли, Борис и Вера не прошли. Второй частый фильтр — по длине, через знакомую len:
words = ['сыр', 'масло', 'кефир']
print([w for w in words if len(w) > 4])
['масло', 'кефир']
Сыр короче пяти букв и вылетел, масло и кефир остались. Граница строгая: слово ровно из пяти букв подошло, а из четырёх — нет, поэтому условие формулируйте по задаче: строго больше или не меньше.
Условия посложнее: and и or
Когда требований два, они соединяются логическими операторами прямо внутри фильтра:
nums = [3, -4, 8, -1, 6]
print([n for n in nums if n > 0 and n % 2 == 0])
print([n for n in nums if n < 0 or n > 5])
[8, 6] [-4, 8, -1, 6]
Первая строка требует и положительность, и чётность — прошли только восемь и шесть. Вторая берёт неположительных и большие пяти сразу: минус четвёрка, минус единица, шесть и восемь. Операторы and и or работают здесь так же, как в обычном if — ничему новому учиться не нужно.
Пустой результат — это нормально
Что вернёт фильтр, если не подошёл никто? Честный пустой список:
odds = [1, 3, 5]
print([n for n in odds if n % 2 == 0])
[]
Пустые квадратные скобки — не ошибка, а корректный ответ на вопрос о чётных среди нечётных. Результат проверяют привычными способами: через len — len(result) == 0 — или по истинности списка в условии, ведь пустой список считается ложью.
if в конце фильтрует, if-else в начале преобразует
Второе место для if внутри comprehension — перед перебором, и смысл там совсем другой. Запись с else выбирает значение для каждого элемента, а не отбрасывает неподходящие:
nums = [4, -2, 7, 0]
print([n if n > 0 else 0 for n in nums])
print([n for n in nums if n > 0])
[4, 0, 7, 0] [4, 7]
Первая строка заменила всё неположительное нулями: элементов осталось столько же, сколько было. Вторая строка выкинула неположительные: список стал короче. Разница в длине результата — самый быстрый способ понять, какая из двух конструкций перед вами.
| Запись | Что делает | Длина результата |
|---|---|---|
| [n for n in nums if n > 0] | Отбирает подходящие элементы | Меньше или равна исходной |
| [n if n > 0 else 0 for n in nums] | Заменяет неподходящие значением | Равна исходной |
nums = [4, -2]
print([n for n in nums if n > 0 else 0])
Фильтр встал в один ряд с построением: comprehension умеет и изменить каждый элемент, и отобрать нужные — а с zip из следующего урока два параллельных списка соединятся в пары значений.
Сначала предскажи ответ в голове — это главный навык программиста.
nums = [1, 2, 3, 4, 5, 6]
print([n for n in nums if n % 2 == 0])
nums = [10, -3, 7, 0]
print([n if n > 0 else 0 for n in nums])
print([n for n in nums if n > 0])
names = ['анна', 'борис']
print([n for n in names if n.startswith('а')])
print([n for n in names if len(n) > 5])
1. Что вернёт [x for x in [1, 2, 3, 4] if x % 2 == 0]?
2. Где стоит if-фильтр внутри comprehension?
3. Что делает [n if n > 0 else 0 for n in nums]?
4. Слово из ровно пяти букв попадёт в [w for w in words if len(w) > 4]?
5. Что вернёт фильтр, если не подошёл ни один элемент?
6. Как в фильтре потребовать сразу положительность и чётность?
Даны числа nums = [12, -5, 8, -20, 3]. Соберите comprehension с фильтром: только положительные чётные числа. Напечатайте результат.
Как отфильтровать список в Python?
Comprehension с условием if в конце: [n for n in nums if n % 2 == 0] оставит только чётные числа. Условие — любое булево выражение: сравнения, len(w) > 4, name.startswith('а'), соединённые and и or. Исходный список фильтр не меняет — строится новый.
Урок 12 раздела Списки: comprehensionЧем if в конце comprehension отличается от if-else в начале?
If в конце после for — фильтр: неподходящие элементы не попадают в результат, список сжимается. If-else перед for — выбор значения: каждый элемент получает значение (подходящее или из else), длина не меняется. Записать фильтр с else нельзя — это SyntaxError.
Что вернёт фильтр, если ничего не нашлось?
Пустой список: comprehension честно соберёт []. Это нормальный результат, а не ошибка — проверяйте его через len(result) == 0 или через истинность: пустой список в условии считается False.
Как поставить два условия в фильтр comprehension?
Соединить их операторами and или or внутри одного if: [n for n in nums if n > 0 and n % 2 == 0] отберёт положительные чётные. Логика та же, что в обычном if; два отдельных if в фильтре comprehension записать нельзя.
filter: функциональный вариант фильтраПонравился урок? Сошлитесь на него
«if в конце comprehension — это фильтр: условие проверяет каждый элемент, и внутрь нового списка попадают только прошедшие проверку.»
Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.
Что дальше
Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.
Что читать дальше
Списки · Урок 12
List comprehension в Python: генератор списков
Задача из списка цен получить список скидок повторяется постоянно — и решается одной формулой вместо цикла из трёх строк. Разбираем list comprehension по частям: выражение, источник и почему исходный список остаётся цел.
Циклы · Урок 7
Оператор continue в Python: пропуск итерации
continue пропускает остаток тела для текущего элемента и переходит к следующему: не выход из цикла, а фильтр в потоке. Сравниваем с break на одних данных.
Функции · Урок 8
filter в Python: оставить подходящие
map менял каждый элемент, а filter выбирает: оставить только чётные, только длинные слова, только заполненные строки. Разбираем filter и его хитрости.
Похожие уроки по темам
Подобраны автоматически по пересечению тем и ключевых слов.
json · Урок 11
Фильтрация данных: найти нужное в JSON
Включение с условием для отбора, next с default для первого подходящего, any и all для вопросов ко всей коллекции — работаем с выгрузкой заказов.
python фильтрация json данныхpython отфильтровать список словарей
json · Урок 15
Фильтрация ответа API: цены, рейтинги, флаги
Товары из ответа API приехали — теперь вопросы: что дешевле N, что в наличии, какая средняя цена и сколько процентов подходит под условие.
фильтрация json pythonсписок словарей фильтр python
Списки · Урок 15
Копия списка в Python: b = a не копия
b = a выглядит как копия, но создаёт вторую ссылку на тот же список: правки через b видны в a. Три способа скопировать по-настоящему и ловушка вложенных списков.
python копия спискаpython скопировать список