У каждого языка программирования есть свои особенности и преимущества. Одна из культовых фишек Python — list comprehension (редко переводится на русский, но можно использовать определение «генератора списка»). Comprehension легко читать, и их используют как начинающие, так и опытные разработчики.
List comprehension — это упрощенный подход к созданию списка, который задействует цикл for, а также инструкции if-else для определения того, что в итоге окажется в финальном списке.
Преимущества list comprehension
У list comprehension есть три основных преимущества.
- Простота. List comprehension позволяют избавиться от циклов for, а также делают код более понятным. В JavaScript, например, есть нечто похожее в виде
map()
иfilter()
, но новичками они воспринимаются сложнее. - Скорость. List comprehension быстрее for-циклов, которые он и заменяет. Это один из первых пунктов при рефакторинге Python-кода.
- Принципы функционального программирования. Это не так важно для начинающих, но функциональное программирование — это подход, при котором изменяемые данные не меняются. Поскольку list comprehensions создают новый список, не меняя существующий, их можно отнести к функциональному программированию.
Создание первого list comprehension
List comprehension записывается в квадратных скобках и задействует цикл for. В процессе создается новый список, куда добавляются все элементы оригинального. По мере добавления элементов их можно изменять.
Для начала возьмем простейший пример: создадим список из цифр от 1 до 5, используя функцию range()
.
>>> nums = [n for n in range(1,6)]
>>> print(nums)
[1, 2, 3, 4, 5]
В этом примере каждое значение диапазона присваивается переменной n
. Каждое значение возвращается неизменным и добавляется в новый список. Это — та самая n
перед циклом for.
В качестве итерируемого объекта не обязательно должна быть функция range()
. Это может быть любое итерируемое значение.
List comprehension с изменением
Теперь пойдем чуть дальше и добавим изменение для каждого значения в цикле.
>>> nums = [1, 2, 3, 4, 5]
>>> squares = [n*n for n in nums]
>>> print(squares)
[1, 4, 9, 16, 25]
В этом примере два изменения по сравнению с прошлым кодом. Во-первых, в качестве источника используется уже существующий список. Во-вторых, list comprehension создает список, где каждое значение — это возведенное в квадрат значения оригинального списка.
List comprehension с if
Теперь добавим проверку с помощью if, чтобы не добавлять все значения.
>>> nums = [1, 2, 3, 4, 5]
>>> odd_squares = [n*n for n in nums if n%2 == 1]
>>> print(odd_squares)
[1, 9, 25]
Инструкция if идет после цикла — в данном случае порядок играет роль.
List comprehension с вложенным циклом for
В последнем примере рассмотрим пример со вложенным циклом for.
>>> matrix = [[x for x in range(1, 4)] for y in range(1, 4)]
>>> print(matrix)
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
Может показаться, что здесь все стало чуть сложнее. Но достаточно разбить код на несколько строк, чтобы увидеть, что нет ничего особенного.
matrix = [
[x for x in range(1, 4)]
for y in range(1, 4)
]
print(matrix)
Последний пример. Создадим список дней рождения из списка словарей. Для этого используем знакомые тактики.
people = [{
"first_name": "Василий",
"last_name": "Марков",
"birthday": "9/25/1984"
}, {
"first_name": "Регина",
"last_name": "Павленко",
"birthday": "8/21/1995"
}]
birthdays = [
person[term]
for person in people
for term in person
if term == "birthday"
]
print(birthdays)
В этом примере мы сперва перебираем people
, присваивая каждый словарь person
. После этого перебираем каждый идентификатор в словаре, присваивая ключи term
. Если значение term
равно birthday
, то значение person[term]
добавляет в list comprehension.
['9/25/1984', '8/21/1995']
Теперь можете попробовать поработать с list comprehension на собственных примерах. Это сделает код более быстрым и компактным.