Заполнение списков с помощью списочных выражений (генераторов списков) в Python

В программировании задача заполнения списка теми или иными значениями возникает часто. Само добавление элемента в список ‒ простое действие, но необходимость использовать цикл при этом делает всю конструкцию создания и заполнения громоздкой. Поэтому в Python был придуман более короткий способ создания готовых списков ‒ списочные выражения (list comprehension), которые представляют собой особую синтаксическую конструкцию.

Списочные выражения относят к так называемому "синтаксическому сахару" языков программирования. Это значит, что без них можно обойтись, но с ними кода становится меньше.

В русском языке списочные выражения часто называют "генераторами списков", потому что в результате их выполнения создается (как бы генерируется) список. Однако в английской документации по Python генераторы ‒ это совсем другое (изучаются в курсе ООП). Поэтому следует помнить, когда речь идет о генераторах, к генераторам списков они не имеют почти никакого отношения.

Если бы мы создавали последовательность натуральных чисел до десяти обычным способом, то наш код мог бы выглядеть так:

>>> a = []
>>> for i in range(10):
...     a.append(i+1)
...
>>> a
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

С генератором списка код сократится до такого:

>>> a = [i+1 for i in range(10)]
>>> a
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Первое, на что следует обратить внимание в выражении [i+1 for i in range(10)], – это квадратные скобки, которые обрамляют всю конструкцию. Именно квадратные скобки говорят нам, что создается список, а не что-то еще.

В находящейся внутри скобок конструкции i+1 for i in range(10) можно выделить три части, которые задает программист, и, следовательно, их содержание может быть произвольным. Это

  1. то, что находится до слова for;
  2. то, что находится между for и in;
  3. то, что находится после слова in.

Ключевые слова for и in, как и квадратные скобки, – неизменные элементы конструкции.

До for указывается элемент, который будет добавляться в список на каждой итерации цикла for. Элемент может создаваться в результате каких-либо действий. По-сути это вынесенное вперед тело цикла. Если тело нельзя записать в одно выражение, от использования генератора списка придется оказаться. Однако не обязательно, чтобы это тело содержало переменную, используемую в цикле. Например, мы можем вызывать какую-нибудь функцию:

>>> a = [input() for i in range(5)]
one
two
three
four
five
>>> a
['one', 'two', 'three', 'four', 'five']

Конструкция for … in … аналогична заголовку обычного цикла for. На каждой итерации мы извлекаем из объекта, указанного после in, очередной элемент и присваиваем его переменной, указанной до in. Причем этих переменных может быть несколько:

>>> a = [10, 5, 3, 8]
>>> b = [j+i for i, j in enumerate(a)]
>>> b
[10, 6, 5, 11]

В примере функция enumerate() на каждой итерации цикла for создает пару, состоящую из индекса элемента и его значения. Первый элемент присваивается переменной i, второй – j. В список b добавляется их сумма.

Существуют расширенные варианты генераторов списков. Во-первых, в них может быть второй (и даже третий) цикл for, выполняющий роль вложенного в первый (пример будет показан в следующем уроке). Во вторых, после for может стоять условный оператор if, который проверяет на что-то элемент. Элемент добавляется в список, только если проходит проверку.

>>> a = [33, 12, 18, 48, 87]
>>> b = [i for i in a if i%2 == 0]
>>> b
[12, 18, 48]

Выше мы фильтруем в список b только четные значения из списка a. Без списочного выражения код выглядел бы так:

>>> a = [33, 12, 18, 48, 87]
>>> b = []
>>> for i in a:
...     if i%2 == 0:
...             b.append(i)
...
>>> b
[12, 18, 48]

Если исходный список далее в программе больше не потребуется, списочное выражение можно присваивать той же переменной, которая связана с перебираемым в цикле списком:

>>> a = [33, 0, 12, -18, 48, -87]
>>> a = [i for i in a if i >= 0]
>>> a
[33, 0, 12, 48]

Практическая работа

  1. С помощью списочного выражения заполните список случайными числами от 0 до 100. С помощью другого выражения отфильтруйте из первого списка только значения, лежащие в диапазоне от 50 до 80.
  2. Заполните список целыми числами, которые пользователь вводит с клавиатуры. Используйте генератор списка.
  3. Дан заполненный список. Выведите в столбик значения его элементов на экран, используя списочное выражение.

Примеры решения и дополнительные уроки в pdf-версии курса


Python. Введение в программирование




Все разделы сайта