Генераторы списков (list comprehensions) позволяют быстро создать список на основе существующих списков. При помощи генератора можно построить список на основе любого итерируемого типа данных (к примеру, из строк или кортежей).
Читайте также:
Синтаксис генераторов списков основан на операторе for, также он может содержать операторы if. Чтобы лучше разобраться в работе генераторов списков, нужно иметь базовые знания о циклах for и условных операторах.
Читайте также:
Генераторы списков предоставляют альтернативный синтаксис для создания списков и других последовательных типов данных. Некоторые методы итерации (например, цикл for) также могут создавать списки, но генераторы позволяют при этом ограничить количество строк кода в программе.
Основы работы с генераторами списков
В Python генераторы списков выглядят так:
list_variable = [x for x in iterable]
Список (или другой итерируемый тип данных, iterable) присваивается переменной. Дополнительные переменные, которые используются как элементы списка, располагаются вокруг оператора for. Ключевое слово in используется так же, как в циклах for, для итерации списка (iterable).
Рассмотрим такой пример, который сгенерирует список из строк:
8host_letters = [letter for letter in '8host']
print(8host_letters)
Переменной 8host_letters присваивается новый список, где letter – элементы, содержащиеся в строке ‘8host’.
Чтобы убедиться, что генератор работает, вызовите функцию print(), и вы получите следующий вывод:
['8', 'h', 'o', 's', 't']
Список, созданный с помощью генератора, состоит из элементов строки ‘8host’.
Генератор списка можно переписать в цикл for, но не каждый цикл for можно переписать в генератор списков.
Попробуем переписать в цикл генератор из примера выше, 8host_letters. Это поможет лучше понять, как работают генераторы.
8host_letters = []
for letter in '8host':
8host_letters.append(letter)
print(8host_letters)
При создании списка с помощью цикла for переменная, которой присвоен список, должна содержать сначала пустой список (обратите внимание на первую строку). Затем цикл итерирует строку ‘8host’ с помощью переменной letter. После этого цикл добавляет каждый последующий элемент из итерируемой строки в список с помощью метода list.append(x).
Читайте также: Методы списков в Python 3
В результате цикл создаст такой же список:
['8', 'h', 'o', 's', 't']
Условные выражения в генераторах списков
Генераторы списков могут использовать условные выражения, чтобы изменить существующие списки или другие последовательные типы данных, и в результате получить новый список.
Давайте рассмотрим генератор с выражением if:
fish_tuple = ('blowfish', 'clownfish', 'catfish', 'octopus')
fish_list = [fish for fish in fish_tuple if fish != 'octopus']
print(fish_list)
Список использует кортеж fish_tuple в качестве основы для нового списка fish_list.
Ключевые слова for и in используются так же, как в предыдущем размере. Кроме того, генератор содержит выражение if, благодаря чему он исключает из списка строку ‘octopus’.
Запросите содержимое списка fish_list и убедитесь, что он содержит все элементы fish_tuple, кроме ‘octopus’.
['blowfish', 'clownfish', 'catfish']
Как видите, с помощью условного выражения можно исключить из нового списка определённый элемент.
Теперь рассмотрим другой пример, в котором используются математические операции, цифры и метод range().
number_list = [x ** 2 for x in range(10) if x % 2 == 0]
print(number_list)
Читайте также:
Новый список number_list будет содержать квадратичные значения каждого чётного элемента в диапазоне от 0-9. В результате получится такой список:
[0, 4, 16, 36, 64]
Давайте разберём этот пример пошагово. Если вместо x ** 2 for x использовать просто x for x, список будет выглядеть так:
number_list = [x for x in range(10)]
print(number_list)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
После этого в генератор было добавлено условное выражение:
number_list = [x for x in range(10) if x % 2 == 0]
print(number_list)
[0, 2, 4, 6, 8]
Выражение if исключило из списка все нечётные числа.
Теперь осталось добавить оператор, который возведёт все элементы в квадрат:
number_list = [x ** 2 for x in range(10) if x % 2 == 0]
print(number_list)
Теперь каждый элемент списка [0, 2, 4, 6, 8] будет возведён в квадрат.
[0, 4, 16, 36, 64]
Также в генераторах можно использовать вложенные выражения if:
number_list = [x for x in range(100) if x % 3 == 0 if x % 5 == 0]
print(number_list)
Читайте также: Условные операторы в Python 3
Такой генератор сначала проверит, делится ли число x на 3, а затем – делится ли оно на 5. Если число отвечает этим условиям, оно добавляется в список.
[0, 15, 30, 45, 60, 75, 90]
Вложенные циклы в генераторах списков
Вложенные циклы используются в программах для выполнения множества итераций.
Рассмотрите следующий цикл for и подумайте, как использовать его в генераторе.
Такой код создаст новый список, который итерирует два других списка и выполнит на их основе математические операции. Код вложенного цикла for выглядит так:
my_list = []
for x in [20, 40, 60]:
for y in [2, 4, 6]:
my_list.append(x * y)
print(my_list)
Результат будет таким:
[40, 80, 120, 80, 160, 240, 120, 240, 360]Этот код умножает элементы первого списка на элементы второго списка при каждой итерации.
Чтобы преобразовать цикл в генератор, нужно объединить тело цикла в одну строку, начиная с операции x * y. Далее будут следовать внешний и внутренний цикл for. Добавьте выражение print(), чтобы просмотреть список и убедиться, что он совпадает со списком, полученным с помощью предыдущего цикла for.
my_list = [x * y for x in [20, 40, 60] for y in [2, 4, 6]]
print(my_list)
[40, 80, 120, 80, 160, 240, 120, 240, 360]
Генератор списка объединяет вложенные циклы for в одну строку кода и получает такой же список.
Заключение
Генераторы списков позволяют с помощью краткого и удобного синтаксиса преобразовать существующий список в новый, что уменьшает объем кода программы.
Генераторы делают код более лаконичным, однако иногда из-за этого код сложно читать. Выбирая между лаконичностью и читабельностью кода, всегда выбирайте читабельность.