Как заполнить список в python циклом for
Перейти к содержимому

Как заполнить список в python циклом for

  • автор:

Однострочный for на Python: списковое включение и генераторные выражения

Maria Hladka

При создании коллекций элементов на Python циклы for заменяются однострочными выражениями. Python поддерживает четыре типа особенных генераторов, называемых также включениями:

  1. Списковые включения (генераторысписков, Listcomps).
  2. Словарные включения (генераторы словарей, Dictcomps).
  3. Множественные включения (генераторы множеств, Setcomps).
  4. Генераторные выражения (GenExp).

Списковое включение

Синтаксис генератора списков устроен следующим образом:

Часть с условием if указывается опционально.

Пример

Давайте создадим список чисел, исключив из него все отрицательные значения — для начала решим задачу с помощью обычного цикла for :

Генератор словарей

Для быстрого, лаконичного и наглядного создания словарей язык программирования Python предлагает воспользоваться специальным сокращением для циклического перебора элементов, известным как “генератор словарей”.

Синтаксис генератора словарей устроен следующим образом:

Пример

Давайте возведем в квадрат все числовые значения словаря при помощи словарного включения:

Генератор множеств

Генератор множества одновременно похож на словарное включение и на списковое включение: фигурные скобки, как у словарей, остальной синтаксис выражения — как у списков. Основное отличие генератора множеств от словарного включения заключается в том, что для генерации словаря указываются ключ и значение через двоеточие, а для генерации множества — одно только значение.

Синтаксис генератора множеств устроен следующим образом:

Пример

Давайте создадим список произвольных чисел и множество парных чисел на его основе:

При помощи генератора множеств подобная программа пишется в одну строчку:

Генераторные выражения

Подобно включениям, выражение генератора предлагает сокращенный синтаксис для цикла for .

Синтаксис генераторных выражений следующий:

Пример

Давайте возведем в квадрат все четные числа списка и отбросим все нечетные.

Для начала решим задачу с помощью обычного цикла for :

С помощью выражения-генератора можно вообще забыть о потребности в функции square_even() и сделать то же самое с помощью одной строки кода:

Генератор кортежей

При взгляде на синтаксис генераторных выражений, сразу же в голову приходит мысль: как написать кортежное включение?

Генераторное выражение можно передавать в качестве параметра любой функции-конструктору стандартных типов данных Python:

Когда включения не подходят?

Только что вы узнали о четырех типах генераторов последовательностей в Python.

Теперь важно научиться избегать соблазна заменить все циклы for в ваших проектах на включения: давайте обсудим, в каких случаях генераторы последовательностей не подходят.

Короче говоря, не используйте включения, когда они снижают качество вашего кода!

Хороший пример — это работа со вложенными циклами for . Если написать вложенный цикл for в виде включения, то код станет короче на несколько строк, но его качество рискует ухудшиться.

Давайте рассмотрим матрицу; она часто представляется в Python как список из списков. Если вы хотите отобразить матрицу в одном измерении, то можете применить двойное списковое включение:

Код лаконичен, но, возможно, не так интуитивно понятно, что он делает: если вместо включения написать вложенный цикл for, то программа сразу станет более понятным:

Производительность генераторных выражений

Наконец, давайте посмотрим на производительность включений в сравнении с обычным циклом for :

Аналогичный бенчмарк для генераторов множеств и словарей дает схожие результаты: включение работает немного быстрей.

Для генераторных выражений сравнение с циклом for + yield бессмысленно: оба возвращают объект-генератор почти мгновенно. Время не тратится на вычисление значений, поскольку генераторы не хранят значения.

Следовательно, не стоит универсально везде применять включения для повышения производительности программ. Выигрыш в скорости выполнения незначителен по сравнению с вредом, наносимым длинными и многословными включениями. Применяйте генераторы последовательностей только тогда, когда это очистит ваш код без снижения его качества.

Выводы

Включения превращают циклы for в однострочные выражения.

Python поддерживает четыре вида включений для стандартных структур данных:

  1. Списковые включения.
  2. Словарные включения.
  3. Множественные включения.
  4. Генераторные выражения.

Разумное применение включений улучшает качество вашего кода, но откажитесь от слепой замены всех циклов на выражения, ведь иногда замена вложенного цикла for на включение снижает понятность кода.

Включения выполняются быстрее, чем цикл for , однако разница — всего 10%, поэтому вместо производительности отдавайте предпочтение качеству кода.

Цикл for в Python

Циклы используются для повторения выполнения определенного блока кода. Например, если нам нужно показать определенное сообщение 100 раз, то мы можем использовать цикл. Это простой пример, но с помощью циклов мы можем сделать многое.

Есть 2 типа циклов в Python:

Цикл for в Python

Цикл for используется для выполнения блока кода определенное количество раз. Он используется с любыми последовательностями, такими как списки, кортежи, строки и др.

Синтаксис цикла for:

Здесь val получает доступ к каждому элементу последовательность на каждой итерации. Цикл продолжается до тех пор, пока не будет достигнут последний элемент в последовательность .

Блок-схема выполнения цикла for в Python:

Рассмотрим пример использования цикла for со списком:

Swift
Python
Go
JavaScript

Здесь мы создали список language . Изначально значением language является первый элемент списка, т.е. Swift , после чего выполняется код внутри цикла — оператор print . Затем language обновляется значением следующего элемента списка, и оператор print выполняется снова. Таким образом, цикл выполняется до тех пор, пока не будет достигнут последний элемент списка.

Цикл for и range()

Диапазон представляет собой ряд значений между двумя числовыми интервалами. В Python используется встроенная функция range() для определения диапазона значений. Например:

Здесь 4 внутри range() определяет диапазон, содержащий значения 0, 1, 2, 3.

В Python мы можем использовать цикл for с диапазонами значений. Например:

Цикл for в одну строку

Как и большинство программистов, вы знаете, что после создания массива, вам нужно написать цикл для его обработки. С этим нет никаких проблем, но иногда нам не нужно использовать несколько строк для написания полного цикла for для одной простой задачи. К частью, Python это понимает и предоставляет замечательный инструмент для использования в таких ситуациях. Этот инструмент называется генератор списка (list comprehensions, списковое включение).

Есть вопросы по Python?

На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!

Telegram Чат & Канал

Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!

Паблик VK

Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!

Что это за зверь?

Списковое включение (List comprehensions) – это списки, которые генерируются с циклом for внутри. Они очень распространены в Python и выглядят примерно следующим образом:

Возможно, вы еще сильнее запутались, так что сделаем шаг назад. Список содержит в себе множество вещей, но определяется между квадратными скобками. Скажем, мне нужно получить функцию, которая удваивает значения всех чисел в списке. Для начала, мне нужно создать список чисел.

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

Вызов этой функции даст нам новый список с удвоенными элементами.

my_doubled_list теперь содержит значения 42 , 4 и 186 . Эта функция простая и делает то, что нам нужно простым способом, но это пять строк, учитывая определяющую строку. Также есть переменная, с которой мы ничего не делаем, кроме как добавляем и в конце возвращаем её.

Единственная часть функции, которая по-настоящему работает – это цикл for. Цикл for тоже мало что делает, просто умножает число на 2. Это идеальный кандидат для превращения в списковое включение.

Создание спискового включения

Давайте сохраним его как функцию, которую мы будем вызывать. Нам нужно только упростить тело функции. Так как списковое включение создает списки, а списки могут быть назначены к переменным, примем это во внимание и расположим списковое включение справа от doubled и продолжим.

Хорошо, теперь нам нужно заполнить правую сторону. Как и с нормальным циклом for, а правая часть списка выглядит именно так, нам нужно назвать элементы в нашем цикле. Сначала, назовем каждый объект, и мы также будем использовать переменную списка, которая будет передана.

Это не может работать в полной мере, так как элемент не является… элементом. В нашей изначальной функции мы выполнили num * 2 , так что давайте сделаем это еще раз.

Все что находится перед циклом for точно внесено в список. Наконец, нам нужно вернуть наш новый список.

Запускаем нашу новую функцию.

И да, my_doubled_list содержит ожидаемые значения 24 , 8 и 404 . Отлично, все работает! Но так как мы создаем и моментально возвращаем переменную, давайте просто применим списковое включение напрямую.

Хорошо, отлично, но зачем мне это нужно?

Списковые включения (генератор списка, list comprehensions) отлично подходят для случаев, когда нам нужно сохранить немного места в коде. Они также удобны в случаях, когда вам просто нужно быстро обработать списки, чтобы сэкономить время над рутинной работой с этим списком.

Они также очень полезны, если вы хотите больше узнать о функциональном программировании, но эту тему мы обсудим в будущем.

Применяем условие if в список

Давайте сделаем новую функцию, которая будет давать только длинные слова из списка. Скажем, каждое слово, которое состоит более чем из 5 букв, будет считаться длинным. Для начала пропишем их вручную.

long_words([‘blog’, ‘Treehouse’, ‘Python’, ‘hi’]) возвращает [‘Treehouse’, ‘Python’] . Это как раз то, чего мы и ожидали.

Хорошо, давайте перепишем это в списковое включение. Для начала, построим то, что мы и так знаем.

Это возвращает нам все слова, не только те, которые длиннее 5 букв. Мы вносим условный оператор в конец цикла for.

Итак, мы использовали всё то же условие if, но поместили его в конец спискового включения. Оно использует то же наименование переменной, которое мы используем для элементов в списке.

Хорошо, давайте опробуем эту версию long_words([‘list’, ‘comprehension’, ‘Treehouse’, ‘Ken’]) возвращает [‘comprehension’, ‘Treehouse’] .

Примеры

1. Возводим в квадрат все числа от 1 до 9. Применяем функцию range.

2. Все цифры которые делятся на 5 без остатка, в диапазоне от 0 до 100.

3. Все цифры которые делятся на 3 и 6 без остатка, в диапазоне от 0 до 50.

4. Первая буква из каждого слова предложения.

5. Заменяем букву А в каждом слове на # .

Итоги

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

Старайтесь сохранять ваши списковые включения короткими, а условия if – простыми. Несложно разглядеть решение многих ваших проблем в списковых включениях и превратить их в огромный беспорядок.

Если это только распалило ваш аппетит, посмотрим, сможете ли вы разобраться со словарными включениями самостоятельно. Они используют конструкторы dict, <:>, но они довольно похожи. Вы также можете проработать установочные включения. Также ознакомьтесь с функциональным программированием в Python, если считаете себя готовым.

Больше примеров

Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.

Цикл for — Python: Списки

Ранее мы рассматривали цикл while . Эта конструкция предназначена для повторения некоего набора действий — все, что выходит за рамки повторения, требует дополнительных средств для хранения состояния.

Возьмем для примера счетчик, который мы изменяем в цикле. При работе с коллекциями нам нужно как-то выбирать, с каким элементом мы работаем в текущей итерации. Так что же, использовать переменную-счетчик каждый раз?

Любой программист всегда стремится автоматизировать рутинную работу, и авторы языков — не исключение. Поэтому в Python для работы с коллекциями существует другой вид цикла — цикл for .

Стоит сразу отметить, что этот цикл не похож на циклы с тем же названием в других языках программирования. Во многих языках этот цикл всего лишь дополняет условие завершения цикла переменной-счетчиком.

Python пошел дальше, поэтому в этом языке цикл for сразу перебирает элементы входной коллекции, и думать об индексе чаще всего вообще не нужно.

Синтаксис

Цикл for устроен очень просто:

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

Пример выше сработает для кортежей и списков — в этом случае будут выведены все элементы. А еще коллекции можно проитерировать — так называют обход коллекции. В таком случае переменная цикла ( element ) будет поочередно содержать все символы строки:

Но что же делать, если нам нужно не просто получить элементы списка один за другим, но и изменить эти элементы? Ведь для этого нам понадобится индекс каждого элемента.

На этот случай в Python есть удобная функция «пронумеровать» — enumerate . Эта функция снабжает каждый элемент индексом, складывая каждый индекс вместе с элементом в кортеж. Кортежи эти, как правило, прямо в первой строке цикла и распаковывают:

В этом цикле мы заменили каждый элемент оригинальным значением, дополненным строкой '!' . Этот код можно было написать и несколько иначе:

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

Это не какая-то особая переменная, а всего лишь соглашение: в Python часто незначимые в этом контексте вещи записывают в переменную _ .

Заметьте: в последнем примере речь и шла об индексах, но мы все равно не использовали длину коллекции. Функция enumerate тоже знает, где остановиться — в конце исходной коллекции.

Управление циклом с помощью break и continue

Иногда не нужно доходить до конца коллекции. Например, при поиске элемента, удовлетворяющего некоему условию. Как только мы нашли первый подходящий элемент, нам неплохо бы сэкономить ресурсы и завершить цикл.

Такой ранний выход из цикла делается с помощью команды break . Вот цикл поиска первого положительного числа:

Как вы могли заметить, переменная цикла оказалась доступна и после его завершения. Однако если коллекция окажется пустой, то переменная не будет определена — имейте это в виду.

Этот код, кажется, работает как надо. Однако если в списке не встретится ни одного положительного числа, то в переменной item окажется просто последний элемент списка.

Как же понять, что мы ничего не нашли? На помощь приходит else . В цикле else выполняется, если цикл так и не прервался с помощью break . Для алгоритмов поиска — это идеальный вариант. Перепишем наш пример с применением else :

Теперь представим ситуацию, что мы в процессе выполнения тела цикла поняли, что остаток тела выполнять незачем и можно сразу перейти к следующей итерации.

Для перехода к следующей итерации предназначена команда continue . Ее использование продемонстрирует следующий пример: мы читаем строки, содержащие строчки кода, но нам не нужно обрабатывать код тех строчек, которые начинаются с символа # . Вот так будет выглядеть код:

Конечно, мы могли бы обойтись условной конструкцией. Однако в этом случае код, обрабатывающий нужные строки, был бы вложен глубже. А нам нужно стремиться держать вложенность кода в разумных пределах, иначе код очень быстро станет очень сложным для прочтения.

break , continue , else и цикл while

Ветка else и команды break и continue доступны и для цикла while . Вот комплексный пример, демонстрирующий все эти возможности:

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

Цикл for и изменяемые коллекции

Хотим предостеречь от изменения состава списка во время обхода его же в цикле for . Программа может завершиться с ошибкой, если вы будете менять список, по которому проходитесь — например, удалять или добавлять новые элементы. Лучше наполнять новый список в процессе обхода старого.

Если вы хотите обязательно изменить состав исходного списка, то обходите в цикле его копию:

Еще можно создать временный список, а потом очистить исходный и добавить элементы из временного:

Естественно можно скомбинировать эти два варианта и сначала сделать копию, потом очистить оригинал, и затем уже в цикле обхода копии добавлять новые элементы.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *