W3docs

Списковые включения

Синтаксис списковых включений Python, фильтрация, вложенные циклы, включения словарей и множеств, а также когда их использовать.

Списковые включения Python

Списковое включение — это краткий способ построить новый список, применяя выражение к каждому элементу итерируемого объекта, с возможностью фильтрации элементов по условию — всё в одну читаемую строку. На этой странице рассматривается полный синтаксис, распространённые шаблоны, включения словарей и множеств, а также рекомендации о том, когда лучше использовать обычный цикл for.

Синтаксис

Общая форма спискового включения:

new_list = [expression for item in iterable if condition]
ЧастьРоль
expressionЗначение, помещаемое в новый список для каждого item
itemПеременная цикла, принимающая поочерёдно каждое значение из iterable
iterableЛюбая последовательность или итерируемый объект: список, кортеж, строка, range и т. д.
if conditionНеобязательный фильтр — включаются только элементы, для которых условие равно True

Часть if condition является необязательной. Если она опущена, каждый элемент итерируемого объекта порождает одну запись в новом списке.

Базовый пример: возведение чисел в квадрат

Эквивалентный цикл for требует трёх строк; списковое включение делает то же самое в одну:

python— editable, runs on the server

Фильтрация с условием

Добавьте клаузу if после итерируемого объекта, чтобы оставить только элементы, удовлетворяющие условию:

python— editable, runs on the server

Можно использовать любой предикат. Например, оставить слова длиннее четырёх символов:

words = ['hi', 'hello', 'world', 'python', 'ai']
long_words = [w for w in words if len(w) > 4]
print(long_words)  # ['hello', 'world', 'python']

if/else в выражении (тернарный оператор)

Когда нужно преобразовать каждый элемент, применяя разную логику в зависимости от условия, поместите if/else внутрь части выражения (перед for), а не после итерируемого объекта:

numbers = range(1, 6)
labels = ['even' if x % 2 == 0 else 'odd' for x in numbers]
print(labels)  # ['odd', 'even', 'odd', 'even', 'odd']

Обратите внимание на разницу:

  • [expr for x in it if cond] — фильтр: пропускает элементы, для которых cond равно False
  • [a if cond else b for x in it] — преобразование: каждый элемент порождает значение, выбираемое по cond

Работа со строками

Списковые включения работают с любым итерируемым объектом, включая строки и списки строк:

words = ['hello', 'world', 'python']
upper_words = [w.upper() for w in words]
print(upper_words)  # ['HELLO', 'WORLD', 'PYTHON']

Извлечение отдельных символов, удовлетворяющих условию:

vowels = [ch for ch in 'programming' if ch in 'aeiou']
print(vowels)  # ['o', 'a', 'i']

Вложенные циклы

Списковые включения поддерживают несколько клауз for, эквивалентных вложенным циклам. Крайний левый for является внешним циклом:

python— editable, runs on the server

Распространённый случай использования вложенных списковых включений — преобразование двумерного списка (матрицы) в одномерный:

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [n for row in matrix for n in row]
print(flat)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

Совет по чтению: мысленно разворачивайте вложенные включения как вложенные циклы for в том же порядке слева направо.

Включения словарей

Та же идея применяется к словарям с использованием {} и выражения key: value:

keys = ['a', 'b', 'c']
values = [1, 2, 3]
mapping = {k: v for k, v in zip(keys, values)}
print(mapping)  # {'a': 1, 'b': 2, 'c': 3}

Поменять ключи и значения в существующем словаре:

original = {'name': 'Alice', 'city': 'Paris'}
inverted = {v: k for k, v in original.items()}
print(inverted)  # {'Alice': 'name', 'Paris': 'city'}

Включения множеств

Используйте {} с одним выражением (без двоеточия), чтобы построить множество, которое автоматически удаляет дубликаты:

numbers = [1, 2, 2, 3, 3, 3, 4]
unique_squares = {x ** 2 for x in numbers}
print(unique_squares)  # {1, 4, 9, 16}

Результат не упорядочен (порядок элементов в множестве не гарантирован), поэтому не полагайтесь на выводимую последовательность.

Производительность

Списковые включения, как правило, быстрее эквивалентных циклов for, вызывающих .append(), поскольку интерпретатор может оптимизировать внутренний цикл на уровне C. Для измерения времени выполнения собственного кода используйте модуль timeit:

import timeit

loop_time = timeit.timeit(
    'result = []\nfor x in range(1000):\n    result.append(x**2)',
    number=10000
)
comp_time = timeit.timeit(
    '[x**2 for x in range(1000)]',
    number=10000
)
print(f'Loop: {loop_time:.3f}s')
print(f'Comprehension: {comp_time:.3f}s')
# Comprehension is typically 20-40% faster

Преимущество в производительности уменьшается или исчезает, когда само выражение работает медленно (сетевой ввод-вывод, тяжёлые вычисления). Профилируйте код перед оптимизацией.

Когда лучше использовать обычный цикл for

Списковые включения подходят не всегда:

СитуацияПредпочтительный вариант
Одиночное преобразование или фильтрацияСписковое включение
Множество побочных эффектов на каждой итерации (логирование, изменение состояния)Цикл for
Сложная логика, требующая нескольких операторовЦикл for
Глубоко вложенные включения (более двух уровней)Цикл for — читаемость важнее
Результат не сохраняется (нужен только обход)Генераторное выражение ((x for x in ...))

Главный признак того, что пора вернуться к циклу for, — когда вам приходится пристально вглядываться в включение, чтобы понять, что оно делает.

Подводные камни

В Python 3 утечки переменных не происходит. Переменная цикла в включении ограничена областью видимости самого включения:

x = 'original'
result = [x * 2 for x in range(3)]
print(x)  # 'original' — not overwritten by the comprehension's x

Избегайте глубоко вложенных включений. Более двух клауз for в одном включении ухудшают читаемость при минимальной пользе. Разбивайте их на именованные промежуточные списки или циклы for.

Генераторные выражения экономят память. Если вам нужно пройти по результату только один раз (например, передать его в sum() или max()), замените [] на (), чтобы получить генератор, выдающий элементы по одному:

total = sum(x ** 2 for x in range(1, 1001))
print(total)  # 333833500

Practice

Практика
What is true about list comprehension in Python according to the information given in the URL?
What is true about list comprehension in Python according to the information given in the URL?
Was this page helpful?