Генераторы Python: Пошаговое введение - Шпаргалка по Python

List Comprehensions — это особый синтаксис, который позволяет нам создавать списки из других списков (Wikipedia, The Python Tutorial). Они невероятно полезны при работе с числами и одним или двумя уровнями вложенных for loops, но сверх этого они могут стать слишком сложными для чтения.
В этой статье мы рассмотрим некоторые For Loops и шаг за шагом перепишем их в виде Comprehensions.
Основы
На самом деле List Comprehensions не слишком сложны, но поначалу их немного трудно понять, потому что они выглядят немного странно. Почему? Ну, порядок, в котором они записаны, противоположен тому, что мы обычно видим в For Loop.
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> for n in names:
... print(n)
# Charles
# Susan
# Patrick
# George
# Carol
Чтобы сделать то же самое с помощью List Comprehension, мы начинаем с самого конца цикла:
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> [print(n) for n in names]
# Charles
# Susan
# Patrick
# George
# Carol
Обратите внимание, как мы поменяли порядок:
- Сначала у нас есть то, что будет результатом цикла
[print(n) ...]. - Затем мы определяем переменную, которая будет хранить каждый из элементов, и указываем на
List,SetилиDictionary, с которым будем работать[... for n in names].
Создание нового списка с помощью включения в список
Это основное применение List Comprehension. Другие варианты могут привести к тому, что код станет трудночитаемым для вас и других.
Вот как мы создаем новый список из существующей коллекции с помощью For Loop:
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> new_list = []
>>> for n in names:
... new_list.append(n)
>>> print(new_list)
# ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
А вот как мы делаем то же самое с помощью List Comprehension:
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> new_list = [n for n in names]
>>> print(new_list)
# ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
Причина, по которой мы можем это сделать, заключается в том, что стандартное поведение List Comprehension — возвращать список:
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> [n for n in names]
# ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
Добавление условий
Что, если мы хотим, чтобы new_list содержал только имена, начинающиеся с C? С For Loop мы бы сделали это так:
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> new_list = []
>>> for n in names:
... if n.startswith('C'):
... new_list.append(n)
>>> print(new_list)
# ['Charles', 'Carol']
В List Comprehension мы добавляем оператор if в конец:
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> new_list = [n for n in names if n.startswith('C')]
>>> print(new_list)
# ['Charles', 'Carol']
Гораздо более читабельно.
Форматирование длинных включений в список
На этот раз мы хотим, чтобы new_list содержал не только имена, начинающиеся с C, но и те, которые заканчиваются на e и содержат k:
>>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol']
>>> new_list = [n for n in names if n.startswith('C') or n.endswith('e') or 'k' in n]
>>> print(new_list)
# ['Charles', 'Patrick', 'George', 'Carol']
Это довольно громоздко. К счастью, Comprehensions можно разбивать на разные строки:
new_list = [
n
for n in names
if n.startswith("C")
or n.endswith("e")
or "k" in n
]
Включения для Set и Dict
Если вы освоили основы List Comprehensions… Поздравляю! Вы только что сделали это с Sets и Dictionaries.
Включение для Set
>>> my_set = {"abc", "def"}
>>> # Здесь мы создаем новый набор с элементами в верхнем регистре с помощью цикла for
>>> new_set = set()
>>> for s in my_set:
... new_set.add(s.upper())
>>> print(new_set)
# {'DEF', 'ABC'}
>>> # То же самое, но с set comprehension
>>> new_set = {s.upper() for s in my_set}
>>> print(new_set)
# {'DEF', 'ABC'}
Включение для Dict
>>> my_dict = {'name': 'Christine', 'age': 98}
>>> # Новый словарь из существующего с помощью цикла for
>>> new_dict = {}
>>> for key, value in my_dict.items():
... new_dict[key] = value
>>> print(new_dict)
# {'name': 'Christine', 'age': 98}
# Использование dict comprehension
>>> new_dict = {key: value for key, value in my_dict.items()} # Обратите внимание на ":"
>>> print(new_dict)
# {'name': 'Christine', 'age': 98}
Рекомендуемая статья: Python Sets: What, Why and How .
Заключение
Каждый раз, когда я узнаю что-то новое, возникает это желание немедленно это использовать. Когда это происходит, я заставляю себя остановиться и подумать на мгновение… Стоит ли мне заменять этот большой, вложенный и уже выглядящий запутанным For Loop на List Comprehension? Вероятно, нет.
Читаемость имеет значение. The Zen of Python.