Абстракция списка Python

Содержание
Введение
Синтаксис
Условные операторы
Фильтрация в отдельной функции
Предварительное изменение
Несколько источников/условий
Вложенные абстракции
Похожие статьи

Введение

List Comprehension - Абстракция списков или списковое включение или генератор списков.

Абстракция списков или списковое включение (англ. list comprehension) в синтаксисе некоторых языков программирования — это способ компактного описания операций обработки списков.

Список можно создать и без применения абстракции списка. Например, с помощью цикла for

>>> squares = [] >>> for i in range(10): squares.append(i * i) >>> squares

Изучив синтаксис абстракции списка можно переписать это решение всего в одну строку

>>> squares = [i * i for i in range(10)] >>> squares

Результат в обоих случаях одинаковый

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Базовый синтаксис

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

new_list = [expression for member in iterable]

[ expr(item) for item in iterable ]

Каждая абстракция списка в Python состоит из трёх элементов (expression, member, iterable):

Ещё один простейший пример:

sites = ["urn.su", "heihei.ru", "devhops.ru", "topbicycle.ru"] print([len(site) for site in sites])

[6, 9, 10, 13]

Потому что выражение довольно гибко для вариаций, абстракция списка работает хорошо там, где можно было бы использовать map()

Пример с map() можете изучить здесь то же самое с абстракцией списка:

>>> txns = [1.09, 23.56, 57.84, 4.56, 6.78] >>> TAX_RATE = .08 >>> def get_price_with_tax(txn): ... return txn * (1 + TAX_RATE) >>> final_prices = [get_price_with_tax(i) for i in txns] >>> final_prices

[1.1772000000000002, 25.4448, 62.467200000000005, 4.9248, 7.322400000000001]

Единственная разница между этим решение и использованием map() состоит в том, что абстракция списка в Python возвращает список а map() возвращает map object.

Выгода от использования абстракции списка

Абстракции списка (List comprehensions) часто описывают как более «питоновский» способ создания списков чер loops или map().

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

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

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

В дополнение к стандартному созданию списков, абстракция списка также может использоваться для сопоставления и фильтрации.

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

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

В качестве дополнительного побочного преимущества всякий раз, когда вы используете абстракцию списка в Python, вам не нужно будет запоминать правильный порядок аргументов, как при вызове map().

Абстракция списка также более декларативна, чем циклы, что означает, что её легче читать и понимать.

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

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

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

Как добавить функциональности абстракциям списка

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

Вы также захотите понять изменения, которые вносятся в понимание списка в Python 3.8.

Использование Conditional Logic

Ранее вы уже видели формулу создания list comprehensions:

new_list = [expression for member in iterable]

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

Самый распростанённый способ добавить условие (conditional logic) к абстракции списка - это добавить его в конец выражения

new_list = [expression for member in iterable (if conditional)]

В этом примере условное выражение находится прямо перед закрывающей скобкой.

Условные выражения полезны тем, что они позволяют абстракциям списков отфильтровывать нежелательные значения без вызова функции filter():

Пример с условием:

sites = ["urn.su", "heihei.ru", "devhops.ru", "topbicycle.ru"] it = ["urn.su", "devhops.ru"] print([len(site) for site in sites if site in it])

[6, 10]

Ещё один пример

>>> sentence = 'the rocket came back from mars' >>> vowels = [i for i in sentence if i in 'aeiou'] >>> vowels

['e', 'o', 'e', 'a', 'e', 'a', 'o', 'a']

В этом примере условное выражение отфильтровывает все символы, которые не являются гласными.

Ещё один пример

from math import sqrt from pprint import pprint as pp def is_prime(x): if x < 2: return False for i in range(2, int(sqrt(x)) + 1): if x % i == 0: return False return True print([x for x in range(101) if is_prime(x)])

python filtering_compreh.py

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

Фильтр в отдельной функции

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

sentence = 'The rocket, who was named Ted, came back \ from Mars because he missed his friends.' def is_consonant(letter): vowels = 'aeiou' return letter.isalpha() and letter.lower() not in vowels consonants = [i for i in sentence if is_consonant(i)] print(consonants)

['T', 'h', 'r', 'c', 'k', 't', 'w', 'h', 'w', 's', 'n', 'm', 'd', \ 'T', 'd', 'c', 'm', 'b', 'c', 'k', 'f', 'r', 'm', 'M', 'r', 's', 'b', \ 'c', 's', 'h', 'm', 's', 's', 'd', 'h', 's', 'f', 'r', 'n', 'd', 's']

В этом примере создан сложный фильтр is_consonant() который передаётся в качестве условного выражения в абстракцию списка.

Обратите внимание, что member значение i передаётся как аргумент в функцию.

Про фильтрацию keyword arguments читайте стать *args, **kwargs

Предварительное изменение

Условное выражение можно поставить в конец для простой фильтрации, но если нужно изменить значение member вместо фильтрации условное выражение нужно поместить в начало:

new_list = [expression (if conditional) for member in iterable]

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

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

>>> original_prices = [1.25, -9.45, 10.22, 3.78, -5.92, 1.16] >>> prices = [i if i > 0 else 0 for i in original_prices] >>> prices

[1.25, 0, 10.22, 3.78, 0, 1.16]

В этом примере выражение i содержит условное выражение if i > 0 else 0.

Это говорит Python вывести значение i если число положительное, но если число отрицательное вывести 0.

Возможно, более понятным будет вариант с отдельной функцией:

>>> def get_price(price): ... return price if price > 0 else 0 >>> prices = [get_price(i) for i in original_prices] >>> prices

[1.25, 0, 10.22, 3.78, 0, 1.16]

Теперь ваше условное выражение содержится внутри функции get_price(), и вы можете использовать его как часть выражения для абстракции списка.

Несколько источников/условий

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

a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] b = [x for i in a for x in i] print(b)

python list_comp.py

[1, 2, 3, 4, 5, 6, 7, 8, 9]

# Multi-input Comprehensions c = [(x, y) for x in range(5) for y in range(5)] print(c) # Without comprehension points = [] for x in range(5): for y in range(5): points.append((x, y)) print(points)

[(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4)] [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4)]

# Multiple if-clauses # Later clauses are nested inside earlier clauses values = [x / (x -y) for x in range(10) if x > 5 for y in range(10) if x - y != 0] print(values) # Without comprehension values = [] for x in range(10): if x > 5: for y in range(10): if x - y != 0: values.append(x / (x - y)) print(values)

[1.0, 1.2, 1.5, 2.0, 3.0, 6.0, -6.0, -3.0, -2.0, 1.0, 1.1666666666666667, 1.4, 1.75, 2.3333333333333335, 3.5, 7.0, -7.0, -3.5, 1.0, 1.1428571428571428, 1.3333333333333333, 1.6, 2.0, 2.6666666666666665, 4.0, 8.0, -8.0, 1.0, 1.125, 1.2857142857142858, 1.5, 1.8, 2.25, 3.0, 4.5, 9.0] [1.0, 1.2, 1.5, 2.0, 3.0, 6.0, -6.0, -3.0, -2.0, 1.0, 1.1666666666666667, 1.4, 1.75, 2.3333333333333335, 3.5, 7.0, -7.0, -3.5, 1.0, 1.1428571428571428, 1.3333333333333333, 1.6, 2.0, 2.6666666666666665, 4.0, 8.0, -8.0, 1.0, 1.125, 1.2857142857142858, 1.5, 1.8, 2.25, 3.0, 4.5, 9.0]

c = [(x, y) for x in range(5) for y in range(x)] print(c)

[(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2), (4, 0), (4, 1), (4, 2), (4, 3)]

Вложенные абстракции

# Nested Comprehensions vals = [[y * 3 for y in range(x)] for x in range(5)] print(vals) # Without Comprehension outer = [] for x in range(5): inner = [] for y in range(x): inner.append(y * 3) outer.append(inner) print(outer)

[[], [0], [0, 3], [0, 3, 6], [0, 3, 6, 9]] [[], [0], [0, 3], [0, 3, 6], [0, 3, 6, 9]]

Пример из статьи про range()

Похожие статьи
Встроенные коллекции
Списки []
list comprehension: Абстракция списка
Python
if, elif, else
Циклы
Абстракция множеств и словарей
Контакты и сотрудничество:
Рекомендую наш хостинг beget.ru
Пишите на info@eth1.ru если Вы:
1. Хотите написать статью для нашего сайта или перевести статью на свой родной язык.
2. Хотите разместить на сайте рекламу, подходящуюю по тематике.
3. Хотите поддержать сайт материально
4. Нашли на сайте ошибку, неточности, баг и т.д. ... .......