Статьи
July 27, 2022

List comprehension в Python

Python известен тем, что даёт разработчикам возможность писать не просто эффективный и лаконичный код. Одним из инструментов для удобного создания списков являются list comprehensions.

Синтаксис list comprehension.

new_list = [expression(element) for element in some_obj if condition]

В квадратные скобки мы записываем выражение, которое будет исполняться для каждого элемента в итерируемом объекте. Из результатов этих действий и будет состоять новый список.

Преимущества list comprehension:

  • Использует меньше памяти и выполняется быстрее, чем обычные циклы.
  • Нужно писать меньше строк кода.

Примеры list comprehension:

Таким кодом вы создаём список с чётными числами до 10:

list_ = [i for i in range(11) if i % 2 == 0]
print(list_)
# [0, 2, 4, 6, 8, 10]

А так можно создать список со списками внутри (как бы "матрицу"), где в каждом вложенном списке будут цифры 1, 2, 3:

matrix = [[j for j in range(3)] for i in range(3)]
print(matrix)

# [[0, 1, 2], [0, 1, 2], [0, 1, 2]]

Сравнение list comprehension и цикла for

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

# Пустой список
list_ = []

# Традиционный способ перебора элементов списка
for character in 'PythonTalk':
    list_.append(character)
    
# Вывод списка
print(list_)
# ['P', 'y', 't', 'h', 'o', 'n', 'T', 'a', 'l', 'k']

А теперь посмотрим на реализацию этой же задачи, но уже с использованием list comprehension:

list_ = [character for character in 'PythonTalk']
print(list_)
# ['P', 'y', 't', 'h', 'o', 'n', 'T', 'a', 'l', 'k']

Использование list comprehension позволяет получить более лаконичный и быстро исполняемый код.

Ниже приведен пример, в котором мы напрямую сравниваем время выполнения цикла for и list comprehension.

# Импортируем необходимый модуль
import time


# Определяем функцию с циклом for
def for_loop(n):
	result = []
	for i in range(n):
		result.append(i ** 2)
	return result


# Определяем функцию с list comprehension
def list_comprehension(n):
	return [i ** 2 for i in range(n)]


# Считаем время выполнения функции for_loop()
begin = time.time()
for_loop(10 ** 10)
end = time.time()
print('Время выполнения for_loop:', round(end - begin, 2))

# Считаем время выполнения функции list_comprehension()
begin = time.time()
list_comprehension(10 ** 10)
end = time.time()
print('Время выполнения list_comprehension:', round(end - begin, 2))

Вывод:

Время выполнения for_loop: 0.8
Время выполнения list_comprehension: 0.74

Как мы можем видеть, использование list comprehension позволяет немного ускорить выполнение программы.

Вложенные list comprehension

Вложенные list comprehension — это использование одних list comprehension внутри других, что очень напоминает вложенные циклы. Ниже приведен пример использования вложенного цикла.

matrix = []

for i in range(3):
	
	# Добавляем пустой подсписок в основной список
	matrix.append([])
	
	for j in range(5):
		matrix[i].append(j)
		
print(matrix)

Теперь сделаем то же самое с помощью list comprehension.

matrix = [[j for j in range(5)] for i in range(3)]

print(matrix)
# [[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]]

List comprehension и lambda-функции

lambda-функции — способ более лаконичного создания функций в Python. Вместе с list comprehension они создают довольно эффективную комбинацию.

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

numbers = []

for i in range(1, 6):
	numbers.append(i * 10)

print(numbers)
# [10, 20, 30, 40, 50]

А так выглядит код, где вместо цикла for мы использовали list comprehension.

numbers = [i * 10 for i in range(1, 6)]
print(numbers)
# Вывод: [10, 20, 30, 40, 50]

И комбинация обоих вариантов:

numbers = list(map(lambda i: i * 10, [i for i in range(1, 6)]))

print(numbers)
# [10, 20, 30, 40, 50]

Иногда комбинация lambda-функции и list comprehension позволит решить сложную задачу буквально одной строчкой кода.

Условные операторы в list comprehension

В list comprehension мы можем использовать и условные операторы. Посмотрим пример:

list_ = ["Even number" if i % 2 == 0 else "Odd number" for i in range(8)]
print(list_)

# ['Even number', 'Odd number', 'Even number', 'Odd number', 
# 'Even number', 'Odd number', 'Even number', 'Odd number']

Можно использовать и вложенные условия:

list_ = [num for num in range(100)
	if num % 5 == 0 if num % 10 == 0]
print(list_)

# [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]

Ниже приведём еще 6 примеров использования list comprehension для закрепления.

Пример 1. Вывод квадратов чисел от 1 до 10

# Получаем квадраты чисел от 1 до 10
squares = [n ** 2 for n in range(1, 11)]

# Выводим квадрат каждого числа
print(squares)
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Пример 2. Транспонирование матрицы

# Инициализируем матрицу
matrix = [[10, 20, 30],
			[40, 50, 60],
			[70, 80, 90]]

# Генерируем транспонированную матрицу
trans = [[i[j] for i in matrix] for j in range(len(matrix))]

print(trans)
# [[10, 40, 70], [20, 50, 80], [30, 60, 90]]

Пример 3. Смена регистра каждого символа в строке при помощи XOR

# Инициализируем строку
string = "PythonTalk"

# Смена регистра каждого символа
list_ = list(map(lambda i: chr(ord(i) ^ 32), string))

# Вывод элементов списка
print(list_)
# ['p', 'Y', 'T', 'H', 'O', 'N', 't', 'A', 'L', 'K']

Пример 4. Запись каждой строки в кортежах задом наперёд

# Переворот каждой строки в кортеже
list_ = [string[::-1] for string in ('Python', 'Talk')]

print(list_)
# ['nohtyP', 'klaT']

Пример 5. Создание списка кортежей из двух отдельных списков при помощи zip

names = ['Oleg', 'Kate', 'Kira']
ages = [32, 31, 1]

person_tuples = [(name, age) for name, age in zip(names, ages)]
print(person_tuples)
# [('Oleg', 33), ('Kate', 32), ('Kira', 1)]

Пример 6. Вывод суммы цифр всех нечётных элементов в списке

# Функция сложения всех цифр в числе
def digit_sum(n):
	dsum = 0
	for ele in str(n):
		dsum += int(ele)
	return dsum


# Инициализируем список
list_ = [367, 111, 562, 945, 6726, 873]

# Используем функцию на нечётных элементах списка
new_list = [digit_sum(i) for i in list_ if i & 1]

print(new_list)
# [16, 3, 18, 18]

Заключение

  • List comprehension — эффективное средство создание новых списков на основе существующих итерируемых объектов.
  • Как правило, list comprehension позволяют проще и лаконичнее создать список, чем стандартные функции и циклы. И исполняется такой код быстрее.
  • Нет необходимости писать длинный код, ведь он изначально получается компактным, понятным и читабельным.
  • Любой list comprehnsion может быть заменён циклом for, но не каждый цикл for можно переписать через list comprehension.
Источник: Geeks for Geeks

👉🏻Подписывайтесь на PythonTalk в Telegram 👈🏻

👨🏻‍💻Чат PythonTalk в Telegram💬

🍩 Поддержать канал 🫶