Генератор списка (List comprehension)

Опубликован: 24.09.2023 130

В Python, как и в любом другом языке программирования, есть своя особая культовая фишка List comprehension - что в переводе на русский язык означает: списковое включение или генератор списков.

По сути, List comprehension - это простой и мощный Pythonic способ создания списков на основе другого итерируемого объекта без использования цикла for или функции map(), буквально одной строкой кода. При этом, List comprehension работает быстрее, чем традиционный способ создания списков с помощью цикла for, за счет оптимизации кода.

Синтаксис: [ expression for item in iterable if condition ]

  • expression - математическое выражение или функция, использующие в качестве аргумента элемент item исходной итерируемой последовательности iterable;
  • iterable — исходный итерируемый объект для создания списка (список, кортеж, словарь, множество, строка и т.п.);
  • condition — условное выражение (необязательная часть генератора), используемое для фильтрации элементов, включаемых в создаваемый список.
# создание списка квадратов целых чисел от 0 до 5
nums_square = [ n **2 for n in range(1, 6) ]
print(nums_square)
[1, 4, 9, 16, 25]

#  создание списка нечетных чисел в диапазоне от -5 до 5 
odd_num = [ x for x in range(-5, 5) if x % 2 != 0 ]
print(odd_num)
[-5, -3, -1, 1, 3] 

Использование условного выражения if ... else в генераторе списков.

Если требуется при создании списка не только отфильтровать исходный итерируемый объект, но и изменить его элементы по какому-либо условию, то используется шаблон List comprehension с условным выражением if ... else.

Применение конструкции if ... else при генерации списков иногда может вызывать сложности, поскольку необходимо правильно размещать эту конструкцию в List comprehension:

  • только до выражения for, а не после.

List comprehension with if ... else

Все дело в том, что Python интерпретирует if ... else как тернарный оператор, принимающий три параметра:

  • условие;
  • значение в случае, если условие верно True;
  • значение в случае, если условие не верно False;

При этом, оператор if ... else возвращает только одно значение (в зависимости от того, верное условие оператора или нет), которое затем используется в выражении for.

Если разместить if ... else после выражения for, то Python выдаст ошибку.

numbers = [22, 13, 45, 50, 98, 69, 43, 44, 1]
new_numbers = [n + 1 if n >= 45 else n + 5 for n in numbers]

print(new_numbers)
[27, 18, 46, 51, 99, 70, 48, 49, 6]

Превращение List comprehension в объект-генератор

Еще одна особенность, которую необходимо учитывать: если в List comprehension заменить квадратные скобки [ ] на круглые ( ), то список превратится в так называемый объект-генератор.

В отличие от списка генератор не хранит все свои элементы в памяти, а выдает каждый элемент последовательности только по запросу согласно заложенной в нем инструкции.

import sys

L = [x * 2 for x in range(10000)]
sys.getsizeof(L)       # определяем память, занимаемую списком L
85176

G = (x * 2 for x in range(10000))
sys.getsizeof(G)      # определяем память, занимаемую генератором G
208

# print(G)
<generator object <genexpr> at 0x7f61f8808b50>

Приведенный пример показывает, что объект-генератор G использует в 409 раз меньше памяти, по сравнению со списком L такого же количества целых чисел. Это является основным преимуществом использования генераторов для создания итерируемых объектов, особенно при работе с большими коллекциями данных.

Аналогично List comprehension Python предоставляет способы быстрого создания словарей Dict comprehension и множеств Set comprehension, синтаксис которых такой же как у генератора списков, только вместо квадратных скобок [] используются фигурные {}.

Похожие посты

Методы преобразования списка в строку и обратно

Удаление дубликатов из списка

Подсчет количества вложенных списков в списке

Поэлементное суммирование списков (кортежей)

Комментариев нет.