Абстракция списков (или «списковое включение», англ. «List Comprehension») — это элегантный способ определения и создания списков на основе существующих списков. Синтаксис абстракции списков в Python следующий:
[выражение for элемент in список]
Примеры абстракции списков
Предположим, мы хотим разделить буквы слова human
и добавить их в качестве элементов списка. Первое, что приходит на ум — это использовать цикл for.
Пример №1: Итерация по строке с помощью цикла for:
1 2 3 4 5 6 |
h_letters = [] for letter in 'human': h_letters.append(letter) print(h_letters) |
Когда мы запустим программу, результатом будет:
['h', 'u', 'm', 'a', 'n']
Однако в Python есть более простой способ решить эту проблему — использовать абстракцию списков.
Давайте посмотрим, как вышеприведенная программа может быть переписана с использованием абстракции списков.
Пример №2: Итерация по строке с помощью абстракции списков:
1 2 |
h_letters = [ letter for letter in 'human' ] print( h_letters) |
Когда мы запустим программу, результатом будет:
['h', 'u', 'm', 'a', 'n']
Здесь переменной h_letters
присваивается новый список, который содержит элементы итерируемой строки 'human'
. Если вы заметили, 'human'
— это строка, а не список. В этом и заключается сила абстракции списков. Оно может определить, когда получает строку или кортеж, и работать с этим объектом как со списком.
Абстракция списков vs. Лямбда-функции
Абстракция списков не является единственным способом работы со списками. Различные встроенные функции и лямбда-функции позволяют создавать и изменять списки за меньшее количество строк кода.
Пример №3: Использование лямбда-функций внутри списка:
1 2 |
letters = list(map(lambda x: x, 'human')) print(letters) |
Результат:
['h','u','m','a','n']
Обычно абстракция списков более читабельна, чем лямбда-функции. Легче понять, чего пытается добиться программист.
Условия в абстракции списков
В абстракции списков можно использовать условия для изменения существующего списка (или других кортежей).
Пример №4: Использование if в абстракции списков:
1 2 |
number_list = [ x for x in range(20) if x % 2 == 0] print(number_list) |
Результат:
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
Список number_list
будет заполнен элементами в диапазоне от 0-19, если значение элемента делится на 2.
Пример №5: Вложенный if в абстракции списков:
1 2 |
num_list = [y for y in range(100) if y % 2 == 0 if y % 5 == 0] print(num_list) |
Результат:
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
Здесь абстракция списков проверяет:
- Делится ли
y
на 2 или нет? - Делится ли
y
на 5 или нет?
Если y
удовлетворяет обоим условиям, y
добавляется в список num_list
.
Пример №6: if…else в абстракции списков:
1 2 |
obj = ["Even" if i%2==0 else "Odd" for i in range(10)] print(obj) |
Результат:
['Even', 'Odd', 'Even', 'Odd', 'Even', 'Odd', 'Even', 'Odd', 'Even', 'Odd']
Здесь абстракция списков проверяет 10 чисел от 0 до 9. Если i
делится на 2, то в список obj
добавляется Even
. Если нет, то добавляется Odd
.
Вложенные циклы в абстракции списков
Предположим, нам нужно вычислить транспонирование матрицы, что требует использования вложенного цикла for.
Пример №7: Транспонирование матрицы с помощью циклов for:
1 2 3 4 5 6 7 8 9 10 11 |
transposed = [] matrix = [[1, 2, 3, 4], [4, 5, 6, 8]] for i in range(len(matrix[0])): transposed_row = [] for row in matrix: transposed_row.append(row[i]) transposed.append(transposed_row) print(transposed) |
Результат:
[[1, 4], [2, 5], [3, 6], [4, 8]]
Здесь используются два цикла for для нахождения транспонирования матрицы. Мы также можем выполнять вложенные итерации внутри списка. А сейчас попробуем найти транспонирование матрицы с помощью вложенного цикла внутри абстракции списков.
Пример №8: Транспонирование матрицы с помощью абстракции списков:
1 2 3 |
matrix = [[1, 2], [3,4], [5,6], [7,8]] transpose = [[row[i] for row in matrix] for i in range(2)] print (transpose) |
Результат:
[[1, 3, 5, 7], [2, 4, 6, 8]]
Здесь у нас есть переменная matrix
, которая имеет 4
строки и 2
столбца. Нам нужно найти транспонирование matrix
. Для этого мы использовали абстракцию списков.
Примечание: Вложенные циклы в абстракции списков работают не так, как обычные вложенные циклы. В приведенной выше программе цикл for i in range(2)
выполняется до row[i] for row in matrix
. Следовательно, сначала переменной i
присваивается значение, а затем элемент, на который указывает row[i]
, добавляется в переменную transpose
.
Ключевые моменты
Абстракция списков — это элегантный способ определения и создания списков на основе существующих списков.
Абстракция списков в целом компактнее и быстрее, чем обычные функции и циклы, для создания списка.
Следует избегать написания очень длинных списков в одной строке с помощью абстракции списков, чтобы код оставался читабелен.
Помните, что любую абстракцию списков можно переписать с помощью цикла for, но не каждый цикл for можно переписать с помощью абстракции списков.