Встроенные функции для коллекций

Теория

У Python есть набор встроенных функций, которые работают с любой коллекцией — списком, кортежем, множеством, ключами словаря и даже строкой. Они закрывают типовые задачи, которые иначе пришлось бы писать циклом: посчитать сумму и количество, найти минимум и максимум, отсортировать, проверить «есть ли хоть один» и «все ли», пронумеровать элементы, пройти по двум спискам одновременно.

Эти функции не меняют исходную коллекцию, а возвращают результат. Отсюда главная путаница: sorted(lst) возвращает новый отсортированный список, а метод lst.sort() сортирует сам список и возвращает None. И ещё одна особенность: на пустой коллекции часть функций падает (min, max), а часть возвращает «нейтральное» значение (sum — 0, any — False, all — True).

Наглядно

Таблица 1. Встроенные функции на ценах корзины prices = [1499, 5990, 990, 490].

Функция Пример Результат На пустой коллекции
len len(prices) 4 0
sum sum(prices) 8969 0
min, max min(prices), max(prices) 490, 5990 ValueError; спасает default=
sorted sorted(prices) новый список [490, 990, 1499, 5990] []
sorted(..., reverse=True) sorted(prices, reverse=True) [5990, 1499, 990, 490] []
reversed list(reversed(prices)) [490, 990, 5990, 1499] []
any any([p > 5000 for p in prices]) True — хотя бы один False
all all([p > 0 for p in prices]) True — все True
enumerate enumerate(names, start=1) пары (номер, элемент) ничего
zip zip(names, prices) пары (название, цена) ничего

Таблица 2. sorted() и метод .sort().

sorted(lst) lst.sort()
Что делает возвращает новый отсортированный список сортирует сам список
Возвращает список None
Исходный список не меняется меняется
С чем работает с любой коллекцией только со списком

На практике

Задача: показать в корзине итоги — сумму, самую дешёвую и дорогую позиции, топ по цене, — проверить наличие и вывести пронумерованный чек.

Шаг 1. Считаем итоги

Количество позиций, сумма, минимум и максимум — каждое одной функцией:

python
prices = [1499, 5990, 990, 490]
print(len(prices), sum(prices), min(prices), max(prices))

Результат:

вывод
4 8969 490 5990

Шаг 2. Считаем среднее

Средний чек — сумма, делённая на количество. На пустой корзине деление на ноль:

python
print(sum(prices) / len(prices))
empty = []
print(sum(empty) / len(empty))

Результат:

вывод
2242.25
ZeroDivisionError: division by zero

Перед делением проверяйте, что коллекция не пуста: sum(x) / len(x) if x else 0.

Шаг 3. Сортируем без изменения исходного

sorted возвращает новый список, исходный порядок цен сохраняется:

python
cheap_first = sorted(prices)
print(cheap_first)
print(prices)

Результат:

вывод
[490, 990, 1499, 5990]
[1499, 5990, 990, 490]

Шаг 4. Сортируем на месте

Метод .sort() меняет сам список и возвращает None:

python
result = prices.sort()
print(result)
print(prices)

Результат:

вывод
None
[490, 990, 1499, 5990]

Если исходный порядок ещё нужен (например, это порядок добавления в корзину), используйте sorted.

Шаг 5. Берём топ

Два самых дорогих товара — сортировка по убыванию и срез:

python
prices = [1499, 5990, 990, 490]
print(sorted(prices, reverse=True)[:2])

Результат:

вывод
[5990, 1499]

Сортировка по полю словаря (например, товары по цене) требует параметра key — он появится в теме «Функции как значения и lambda».

Шаг 6. Проверяем «хоть один» и «все»

any — есть ли хотя бы одно истинное значение, all — истинны ли все. Список условий удобно собрать comprehension:

python
stocks = [12, 0, 40]
print(any([s == 0 for s in stocks]))
print(all([s > 0 for s in stocks]))
print(any([]), all([]))

Результат:

вывод
True
False
False True

all([]) — True: на пустом наборе нет ни одного нарушения.

Шаг 7. Нумеруем через enumerate

Чек с номерами строк. enumerate выдаёт пары (номер, элемент), нумерация по умолчанию с нуля:

python
names = ["Мышь", "Коврик", "Кабель"]
for number, name in enumerate(names, start=1):
    print(f"{number}. {name}")

Результат:

вывод
1. Мышь
2. Коврик
3. Кабель

Шаг 8. Идём по двум спискам через zip

Названия и цены лежат в разных списках — zip собирает пары по позициям:

python
prices = [1499, 490, 390]
for name, price in zip(names, prices):
    print(f"{name}: {price} ₽")
print(dict(zip(names, prices)))
print(list(zip(names, [1499, 490])))

Результат:

вывод
Мышь: 1499 ₽
Коврик: 490 ₽
Кабель: 390 ₽
{'Мышь': 1499, 'Коврик': 490, 'Кабель': 390}
[('Мышь', 1499), ('Коврик', 490)]

Последняя строка: если списки разной длины, zip молча останавливается на коротком — «Кабель» пропал без ошибки. С Python 3.10 можно включить проверку: zip(a, b, strict=True) выбросит ValueError.

Шаг 9. Обрабатываем пустую коллекцию

max пустого списка падает. Параметр default задаёт ответ на этот случай:

python
print(max([], default=0))
max([])

Результат:

вывод
0
ValueError: max() iterable argument is empty

Частые ошибки

  • lst = lst.sort(). Метод возвращает None — список теряется. Новый отсортированный список — sorted(lst).
  • Сортировка исходных данных. .sort() меняет список, который может понадобиться в исходном порядке. Если сомневаетесь — sorted.
  • min / max пустой коллекции. ValueError; используйте default=.
  • Деление на len пустой коллекции. ZeroDivisionError; проверьте, что коллекция не пуста.
  • Нумерация с нуля. enumerate начинает с 0; для людей — start=1.
  • zip разной длины. Лишние элементы теряются без ошибки; там, где длины обязаны совпадать, — strict=True.

Итог

Подсчёт

  • len, sum, min, max — работают с любой коллекцией.
  • min/max пустой коллекции — ValueError, спасает default=; sum([]) — 0.

Сортировка

  • sorted(x) — новый список, исходный не меняется; reverse=True — по убыванию.
  • lst.sort() — на месте, возвращает None.

Проверки

  • any(...) — хоть один истинный; all(...) — все истинны; any([]) — False, all([]) — True.

Обход

  • enumerate(x, start=1) — пары (номер, элемент).
  • zip(a, b) — пары по позициям, останавливается на коротком; strict=True — проверка длины.
  • dict(zip(keys, values)) — словарь из двух списков.

Вопросы на собеседовании

Чем sorted() отличается от list.sort()?

sorted() принимает любую коллекцию и возвращает новый список, не меняя исходную. list.sort() есть только у списков, сортирует на месте и возвращает None. Обе сортировки стабильные: равные элементы сохраняют исходный порядок.

Что вернут any([]) и all([])?

False и True. any ищет хотя бы один истинный элемент — в пустом наборе его нет. all проверяет, что нет ни одного ложного, — в пустом наборе их тоже нет.

Что делает zip, если списки разной длины?

Останавливается на самом коротком, лишние элементы длинных списков отбрасываются без ошибки. С Python 3.10 zip(..., strict=True) выбрасывает ValueError при разной длине.

Глубже

Почему zip, enumerate и reversed не создают списки, а выдают элементы по одному, — в курсе «Python под капотом», раздел «Итерация и протоколы».

Ошибка в тексте

Сообщить об ошибке могут зарегистрированные пользователи — так в сообщениях меньше спама.

Войти, чтобы сообщить