July 3, 2020

Генераторы списков в Python

В языке программирования Python существует специальная синтаксическая конструкция, которая позволяет по определенным правилам создавать заполненные списки. Такие конструкции называются генераторами списков. Их удобство заключается в более короткой записи программного кода, чем если бы создавался список обычным способом.

Например, надо создать список, заполненный натуральными числами до определенного числа. "Классический" способ будет выглядеть примерно так:

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

На создание списка ушло три строчки кода. Генератор же сделает это за одну:

>>> a = [i for i in range(1,15)]
>>> a
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

Здесь конструкция [i for i in range(1,15)] является генератором списка. Вся конструкция заключается в квадратные скобки, что как бы говорит, что будет создан список. Внутри квадратных скобок можно выделить три части: 1) что делаем с элементом (в данном случае ничего не делаем, просто добавляем в список), 2) что берем (в данном случае элемент i), 3) откуда берем (здесь из объекта range). Части отделены друг от друга ключевыми словами for и in.

Рассмотрим такой пример:

>>> a = [2,-2,4,-4,7,5]
>>> b = [i**2 for i in a]
>>> b
[4, 4, 16, 16, 49, 25]

В данном случае в генераторе списка берется каждый элемент из списка a и возводится в квадрат. Таким образом, 1) что делаем - возводим элемент в квадрат, 2) что берем - элемент, 3) откуда берем - из списка a.

>>> a = {1:10, 2:20, 3:30}
>>> b = [i*a[i] for i in a]
>>> b
[10, 40, 90]

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

В конец генератора можно добавлять конструкцию if. Например, надо из строки извлечь все цифры:

>>> a = "lsj94ksd231 9"
>>> b = [int(i) for i in a if '0'<=i<='9']
>>> b
[9, 4, 2, 3, 1, 9]

Или заполнить список числами, кратными 30 или 31:

>>> a = [i for i in range(30,250) if i%30 == 0 or i%31 == 0]
>>> a
[30, 31, 60, 62, 90, 93, 120, 124, 150, 155, 180, 186, 210, 217, 240, 248]

Таким образом, генераторы позволяют создавать списки легче и быстрее. Однако заменить ими достаточно сложные конструкции не получится. Например, когда условие проверки должно включать ветку else.