Как и большинство программистов, вы знаете, что после создания массива, вам нужно написать цикл для его обработки. С этим нет никаких проблем, но иногда нам не нужно использовать несколько строк для написания полного цикла for для одной простой задачи. К частью, Python это понимает и предоставляет замечательный инструмент для использования в таких ситуациях. Этот инструмент называется генератор списка (list comprehensions, списковое включение).
Есть вопросы по Python?
На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!
Паблик VK
Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!
Что это за зверь?
Списковое включение (List comprehensions) – это списки, которые генерируются с циклом for внутри. Они очень распространены в Python и выглядят примерно следующим образом:
1 |
[thing for thing in list_of_things] |
Возможно, вы еще сильнее запутались, так что сделаем шаг назад. Список содержит в себе множество вещей, но определяется между квадратными скобками. Скажем, мне нужно получить функцию, которая удваивает значения всех чисел в списке. Для начала, мне нужно создать список чисел.
1 |
my_list = [21, 2, 93] |
Теперь создадим функцию. Назовем ее list_doubler
, так как это именно то, что она делает, и она будет принимать аргумент, который является списком, который мы будем удваивать.
1 2 3 4 5 |
def list_doubler(lst): doubled = [] for num in lst: doubled.append(num*2) return doubled |
Вызов этой функции даст нам новый список с удвоенными элементами.
1 |
my_doubled_list = list_doubler(lst) |
my_doubled_list
теперь содержит значения 42
, 4
и 186
. Эта функция простая и делает то, что нам нужно простым способом, но это пять строк, учитывая определяющую строку. Также есть переменная, с которой мы ничего не делаем, кроме как добавляем и в конце возвращаем её.
Единственная часть функции, которая по-настоящему работает – это цикл for. Цикл for тоже мало что делает, просто умножает число на 2. Это идеальный кандидат для превращения в списковое включение.
Создание спискового включения
Давайте сохраним его как функцию, которую мы будем вызывать. Нам нужно только упростить тело функции. Так как списковое включение создает списки, а списки могут быть назначены к переменным, примем это во внимание и расположим списковое включение справа от doubled
и продолжим.
1 |
doubled = [thing for thing in list_of_things] |
Хорошо, теперь нам нужно заполнить правую сторону. Как и с нормальным циклом for, а правая часть списка выглядит именно так, нам нужно назвать элементы в нашем цикле. Сначала, назовем каждый объект, и мы также будем использовать переменную списка, которая будет передана.
1 |
doubled = [thing for num in lst] |
Это не может работать в полной мере, так как элемент не является… элементом. В нашей изначальной функции мы выполнили num * 2
, так что давайте сделаем это еще раз.
1 |
doubled = [num * 2 for num in lst] |
Все что находится перед циклом for
точно внесено в список. Наконец, нам нужно вернуть наш новый список.
1 2 3 |
def list_doubler(lst): doubled = [num * 2 for num in lst] return doubled |
Запускаем нашу новую функцию.
1 |
my_doubled_list = list_doubler([12, 4, 202]) |
И да, my_doubled_list
содержит ожидаемые значения 24
, 8
и 404
. Отлично, все работает! Но так как мы создаем и моментально возвращаем переменную, давайте просто применим списковое включение напрямую.
1 2 |
def list_doubler(lst): return [num * 2 for num in lst] |
Хорошо, отлично, но зачем мне это нужно?
Списковые включения (генератор списка, list comprehensions) отлично подходят для случаев, когда нам нужно сохранить немного места в коде. Они также удобны в случаях, когда вам просто нужно быстро обработать списки, чтобы сэкономить время над рутинной работой с этим списком.
Они также очень полезны, если вы хотите больше узнать о функциональном программировании, но эту тему мы обсудим в будущем.
Применяем условие if в список
Давайте сделаем новую функцию, которая будет давать только длинные слова из списка. Скажем, каждое слово, которое состоит более чем из 5 букв, будет считаться длинным. Для начала пропишем их вручную.
1 2 3 4 5 6 |
def long_words(lst): words = [] for word in lst: if len(word) > 5: words.append(word) return words |
Мы создали переменную для хранения наших слов, применяем цикл над всеми словами в нашем списке, и проверяем длинну каждого слова. Если оно длиннее 5 букв, мы вносим слово в список, и затем, наконец, мы отсылаем список назад. Давайте попробуем.
long_words(['blog', 'Treehouse', 'Python', 'hi'])
возвращает ['Treehouse', 'Python']
. Это как раз то, чего мы и ожидали.
Хорошо, давайте перепишем это в списковое включение. Для начала, построим то, что мы и так знаем.
1 2 |
def long_words(lst): return [word for word in lst] |
Это возвращает нам все слова, не только те, которые длиннее 5 букв. Мы вносим условный оператор в конец цикла for.
1 2 |
def long_words(lst): return [word for word in lst if len(word) > 5] |
Итак, мы использовали всё то же условие if, но поместили его в конец спискового включения. Оно использует то же наименование переменной, которое мы используем для элементов в списке.
Хорошо, давайте опробуем эту версию long_words(['list', 'comprehension', 'Treehouse', 'Ken'])
возвращает ['comprehension', 'Treehouse']
.
Примеры
1. Возводим в квадрат все числа от 1 до 9. Применяем функцию range.
1 |
[x**2 for x in range(10)] |
Результат:
1 |
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81] |
2. Все цифры которые делятся на 5 без остатка, в диапазоне от 0 до 100.
1 |
[x for x in range(100) if x%5 == 0] |
Результат:
1 |
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95] |
3. Все цифры которые делятся на 3 и 6 без остатка, в диапазоне от 0 до 50.
1 |
[x for x in range(50) if x%3 == 0 and x%6 != 0] |
Результат:
1 |
[3, 9, 15, 21, 27, 33, 39, 45] |
4. Первая буква из каждого слова предложения.
1 2 |
phrase = "Тестовое сообщение из мира Python для сообщества." print([w[0] for w in phrase.split()]) |
Результат:
1 |
['Т', 'с', 'и', 'м', 'P', 'д', 'с'] |
5. Заменяем букву А
в каждом слове на #
.
1 2 |
phrase = "АБАЖУР, АБАЗИНСКИЙ, АБАЗИНЫ, АББАТ, АББАТИСА, АББАТСТВО" print(''.join([letter if letter != 'А' else '#' for letter in phrase])) |
Результат:
1 |
#Б#ЖУР, #Б#ЗИНСКИЙ, #Б#ЗИНЫ, #ББ#Т, #ББ#ТИС#, #ББ#ТСТВО |
Итоги
Надеюсь это руководство помогло вам понять простой способ экономии кода , который вам нужно написать для получения конкретной готовой работы с вашими списками.
Старайтесь сохранять ваши списковые включения короткими, а условия if – простыми. Несложно разглядеть решение многих ваших проблем в списковых включениях и превратить их в огромный беспорядок.
Если это только распалило ваш аппетит, посмотрим, сможете ли вы разобраться со словарными включениями самостоятельно. Они используют конструкторы dict, {:} , но они довольно похожи. Вы также можете проработать установочные включения. Также ознакомьтесь с функциональным программированием в Python, если считаете себя готовым.
Больше примеров
Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.
E-mail: vasile.buldumac@ati.utm.md
Образование
Universitatea Tehnică a Moldovei (utm.md)
- 2014 — 2018 Технический Университет Молдовы, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
- 2018 — 2020 Технический Университет Молдовы, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»