Статьи

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

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

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

Основные списки, которые не используют никаких условий, имеют следующую форму:

1
[<the_expression> for <the_element> in <the_iterable>]

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

1
2
3
4
5
6
7
multiples = []
 
for n in range(1,16):
    multiples.append(n*5)
     
print(multiples)
# [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75]

Вышеуказанный цикл for основном имеет следующую структуру:

1
2
for <the_element> in <the_iterable>:
   <the_expression>

Если вы сравните его с формой понимания списка, которую вы прочитали ранее, вы увидите, что <the_element> равен n , <the_iterable>range(1,16) , а <the_expression>n*5 . Помещение этих значений в список понимания даст нам следующий результат:

1
2
3
4
multiples = [n*5 for n in range(1,15)]
 
multiples
# [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70]

Точно так же вы можете получить список с кубом заданных чисел, например так:

1
2
3
4
cubes = [n**3 for n in range(1,16)]
 
print(cubes)
#[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000, 1331, 1728, 2197, 2744, 3375]

Вы также можете использовать условие if чтобы отфильтровать определенные значения из окончательного списка. В этом случае понимание списка принимает следующую форму:

1
[<the_expression> for <the_element> in <the_iterable> if <the_condition>]

Основным примером такого типа понимания может быть получение всех четных чисел в заданном диапазоне. Цикл for для выполнения этой задачи будет выглядеть так:

1
2
3
4
5
6
7
8
evens = []
 
for n in range(1,21):
    if n%2 == 0:
        evens.append(n)
         
print(evens)
# [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

То же самое может быть достигнуто с помощью следующего понимания списка:

1
2
3
4
evens = [n for n in range(1,21) if n%2 == 0]
 
print(evens)
# [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

Более сложным примером использования списочных представлений было бы добавление .. if .. else .. условных выражений внутри них.

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

1
[<the_expression> if <the_condition> else <other_expression> for <the_element> in <the_iterable>]

Давайте начнем с написания подробного условного выражения .. if .. else .. чтобы получить квадраты четных чисел и кубы нечетных чисел в заданном диапазоне.

01
02
03
04
05
06
07
08
09
10
squares_cubes = []
 
for n in range(1,16):
    if n%2 == 0:
        squares_cubes.append(n**2)
    else:
        squares_cubes.append(n**3)
         
print(squares_cubes)
# [1, 4, 27, 16, 125, 36, 343, 64, 729, 100, 1331, 144, 2197, 196, 3375]

Вышеуказанное условное выражение имеет следующую структуру:

1
2
3
4
5
for <the_element> in <the_iterable>:
   if <the_condition>:
       <the_expression>
   else:
       <other_expression>

Размещение соответствующих значений в нужных местах даст вам следующее понимание списка:

1
2
3
4
squares_cubes = [n**2 if n%2 == 0 else n**3 for n in range(1,16)]
 
print(squares_cubes)
# [1, 4, 27, 16, 125, 36, 343, 64, 729, 100, 1331, 144, 2197, 196, 3375]

Вы также можете использовать вложенные циклы в пределах понимания списка. Не существует ограничения на число циклов for которые вы можете поместить в понимание списка. Однако вы должны иметь в виду, что порядок циклов должен быть одинаковым как в исходном коде, так и в понимании списка. Вы также можете добавить необязательное условие if после каждого цикла for . Понимание списка с вложенными циклами for будет иметь следующую структуру:

1
2
3
4
[ <the_expression> for <element_a> in <iterable_a> (optional if <condition_a>)
                  for <element_b> in <iterable_b> (optional if <condition_b>)
                  for <element_c> in <iterable_c> (optional if <condition_c>)
                  … and so on …]

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

1
2
3
4
5
6
7
8
multiplications = []
 
for i in range(1, 4):
    for n in range(1, 11):
        multiplications.append(i*n)
 
print(multiplications)
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30]

Эти вложенные циклы могут быть переписаны как:

1
2
3
for <element_a> in <iterable_a>:
   for <element_b> in <iterable_b>:
       <the_expression>

После того, как вы написали цикл в этой форме, преобразовать его в понимание списка легко:

1
2
3
4
multiplications = [i*n for i in range(1,4) for n in range(1,11)]
 
print(multiplications)
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30]

Вы также можете использовать аналогично написанное понимание списка, чтобы сгладить список списков. Внешний цикл for перебирает отдельные списки и сохраняет их в row переменных. Внутренний цикл for затем будет перебирать все элементы в текущей row . Во время первой итерации переменная row имеет значение [1, 2, 3, 4] . Второй цикл перебирает этот список или row и добавляет все эти значения в окончательный список.

01
02
03
04
05
06
07
08
09
10
matrix = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
]
 
flatten = [n for row in matrix for n in row]
 
print(flatten)
#[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

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

Без выражения понимания списка вам понадобится использовать два цикла for для создания транспонирования.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
matrix = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
]
 
transpose = []
 
for i in range(4):
    temp = []
    for row in matrix:
        temp.append(row[i])
    transpose.append(temp)
     
print(transpose)
# [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

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

Вот приведенный выше код в форме понимания списка:

01
02
03
04
05
06
07
08
09
10
matrix = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
]
 
transpose = [[row[n] for row in matrix] for n in range(4)]
 
print(transpose)
# [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

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

1
[<the_expression> for <the_element> in <the_iterable>]

Если вы сравните его с пониманием вложенного списка выше, вы увидите, что <the_expression> в этом случае фактически является другим пониманием списка: [row[n] for row in matrix] . Это понимание вложенного списка само по себе имеет форму цикла for .

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

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

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