Заполнение списков с помощью списочных выражений (генераторов списков) в 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)
можно выделить три части, которые задает программист, и, следовательно, их содержание может быть произвольным. Это
- то, что находится до слова
for
; - то, что находится между
for
иin
; - то, что находится после слова
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]
Практическая работа
- С помощью списочного выражения заполните список случайными числами от 0 до 100. С помощью другого выражения отфильтруйте из первого списка только значения, лежащие в диапазоне от 50 до 80.
- Заполните список целыми числами, которые пользователь вводит с клавиатуры. Используйте генератор списка.
- Дан заполненный список. Выведите в столбик значения его элементов на экран, используя списочное выражение.
Примеры решения и дополнительные уроки в pdf-версии курса