Поиск по сайту:

Понимание понимания списков в Python 3


Введение

Включение списков предлагает лаконичный способ создания кортежей.

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

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

Предпосылки

У вас должен быть установлен Python 3 и настроена среда программирования на вашем компьютере или сервере. Если у вас не настроена среда программирования, вы можете обратиться к руководствам по установке и настройке среды программирования на вашем сервере, подходящей для вашей операционной системы (Ubuntu, CentOS, Debian и т. д.).

Список понятий

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

Информация: Чтобы следовать примеру кода в этом руководстве, откройте интерактивную оболочку Python в вашей локальной системе, выполнив команду python3. Затем вы можете копировать, вставлять или редактировать примеры, добавляя их после приглашения >>>.

list_variable = [x for x in iterable]

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

Давайте посмотрим на пример, который создает список на основе строки:

shark_letters = [letter for letter in 'shark']
print(shark_letters)

Здесь новый список назначается переменной shark_letters, а letter используется для замены элементов, содержащихся в итерируемой строке shark.

Чтобы подтвердить, как выглядит новый список shark_letters, мы вызываем его для print() и получаем следующий вывод:

Output
['s', 'h', 'a', 'r', 'k']

Список, который мы создали с помощью генератора списков, состоит из элементов строки shark, то есть по одной строке на каждую букву.

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

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

shark_letters = []

for letter in 'shark':
    shark_letters.append(letter)

print(shark_letters)

При создании списка с циклом for переменная, назначенная списку, должна быть инициализирована пустым списком, как это находится в первой строке нашего блока кода. Затем цикл for перебирает элемент, используя переменную letter в итерируемой строке shark. В цикле for каждый элемент в строке добавляется в список с помощью метода list.append(x).

Переписав понимание списка как цикл for, мы получим тот же результат:

Output
['s', 'h', 'a', 'r', 'k']

Включение списков можно переписать как циклы for, а некоторые циклы for можно переписать в списки, чтобы сделать код более кратким.

Использование условных выражений со списками

Генераторы списков могут использовать условные операторы для изменения существующих списков или других последовательных типов данных при создании новых списков.

Давайте посмотрим на пример оператора if, используемого в понимании списка:

fish_tuple = ('blowfish', 'clownfish', 'catfish', 'octopus')

fish_list = [fish for fish in fish_tuple if fish != 'octopus']
print(fish_list)

Понимание списка использует кортеж fish_tuple в качестве основы для нового списка с именем fish_list. Ключевые слова for и in используются, как и в предыдущем разделе, а теперь добавлен оператор if. Оператор if указывает добавлять только те элементы, которые не эквивалентны строке octopus, поэтому новый список принимает только те элементы из кортежа, которые не соответствуют осьминог.

Когда мы запустим это, мы заметим, что fish_list содержит те же строковые элементы, что и fish_tuple, за исключением того факта, что строка octopus была опущена. :

Output
['blowfish', 'clownfish', 'catfish']

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

Мы создадим еще один пример, в котором используется тип последовательности range().

number_list = [x ** 2 for x in range(10) if x % 2 == 0]
print(number_list)

Создаваемый список number_list будет заполнен квадратными значениями каждого элемента в диапазоне от 0 до 9, если значение элемента делится на 2. Результат будет следующим:

Output
[0, 4, 16, 36, 64]

Чтобы еще немного разобраться в том, что делает понимание списка, давайте подумаем о том, что было бы напечатано, если бы мы вызывали только x вместо x в диапазоне (10). Наша небольшая программа и выходные данные будут выглядеть следующим образом:

number_list = [x for x in range(10)]
print(number_list)
Output
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Теперь добавим условное выражение:

number_list = [x for x in range(10) if x % 2 == 0]
print(number_list)
Output
[0, 2, 4, 6, 8]

Оператор if ограничил элементы в окончательном списке, чтобы включить только те элементы, которые делятся на 2, опуская все нечетные числа.

Наконец, мы можем добавить оператор для возведения каждого x в квадрат:

number_list = [x ** 2 for x in range(10) if x % 2 == 0]
print(number_list)

Таким образом, каждое из чисел в предыдущем списке [0, 2, 4, 6, 8] теперь возведено в квадрат:

Output
[0, 4, 16, 36, 64]

Вы также можете реплицировать вложенные операторы if с пониманием списка:

number_list = [x for x in range(100) if x % 3 == 0 if x % 5 == 0]
print(number_list)

Здесь генератор списка сначала проверит, делится ли число x на 3, а затем проверит, делится ли x на 5. Если x удовлетворяет обоим требованиям, которые он напечатает, и выводит:

Output
[0, 15, 30, 45, 60, 75, 90]

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

Вложенные циклы в понимании списка

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

На этот раз мы рассмотрим существующую конструкцию вложенного цикла for и будем работать над пониманием списка.

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

my_list = []

for x in [20, 40, 60]:
	for y in [2, 4, 6]:
		my_list.append(x * y)

print(my_list)

Когда мы запускаем этот код, мы получаем следующий вывод:

Output
[40, 80, 120, 80, 160, 240, 120, 240, 360]

Этот код умножает элементы в первом списке на элементы во втором списке на каждой итерации.

Чтобы преобразовать это в понимание списка, мы объединим каждую из строк кода в одну строку, начиная с операции x * y. За ним следует внешний цикл for, затем внутренний цикл for. Мы добавим оператор print() ниже нашего понимания списка, чтобы подтвердить, что новый список соответствует списку, который мы создали с помощью нашего вложенного блока цикла for выше:

my_list = [x * y for x in [20, 40, 60] for y in [2, 4, 6]]
print(my_list)
Output
[40, 80, 120, 80, 160, 240, 120, 240, 360]

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

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

Заключение

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

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

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