Перейти к содержанию

432 уроков, 26 библиотек и челлендж «Что выведет код?» — бесплатно, код прямо в браузере

Начать обучение
Урок 13 из 20 Начальный 15 мин 100 XP

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])
Здесь SyntaxError: у фильтра в конце перебора не бывает else. Если нужен выбор значения, вся конструкция if-else ставится перед for: [n if n > 0 else 0 for n in nums].

Фильтр встал в один ряд с построением: 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])
Проверь себя
0 / 6

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. Как в фильтре потребовать сразу положительность и чётность?

Карточки терминов
Запомнено: 0 / 7
Практика

Даны числа nums = [12, -5, 8, -20, 3]. Соберите comprehension с фильтром: только положительные чётные числа. Напечатайте результат.

practice.py
Вопросы и ответы по уроку

Как отфильтровать список в 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-канал или свой блог — так о проекте узнают новые читатели.

TelegramVK

Что дальше

Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.

Похожие уроки по темам

Подобраны автоматически по пересечению тем и ключевых слов.