W3docs

Сортировка списков

Как сортировать списки Python с помощью sorted() и sort(), использовать параметр key, сортировать в обратном порядке и работать с объектами.

Сортировка списка — одна из наиболее частых операций в Python. Python предоставляет два встроенных инструмента для этого: функция sorted(), которая возвращает новый отсортированный список, не изменяя оригинал, и метод list.sort(), который сортирует список на месте. Оба принимают флаг reverse для сортировки по убыванию и параметр key для пользовательской логики сортировки.

Эта глава охватывает:

  • sorted() — сортировка любого итерируемого объекта в новый список
  • list.sort() — сортировка списка на месте
  • Сортировка по возрастанию и убыванию
  • Параметр key — сортировка по длине, полю или любому пользовательскому критерию
  • Сортировка без учёта регистра
  • Сортировка списков словарей и пользовательских объектов
  • Многоключевая сортировка
  • operator.itemgetter как эффективная альтернатива lambda

Для знакомства с основами списков смотрите главы Python Lists и List Methods.

Функция sorted()

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

Синтаксис:

sorted(iterable, *, key=None, reverse=False)
  • iterable — последовательность для сортировки
  • key — необязательная функция с одним аргументом, применяемая к каждому элементу перед сравнением (по умолчанию: сравнение элементов напрямую)
  • reverse — установите True для сортировки по убыванию (по умолчанию: False)

Сортировка списка строк

python— editable, runs on the server

Сортировка списка чисел

Числовые списки сортируются по величине, а не по строковому представлению (поэтому 10 не идёт раньше 9).

nums = [3, 1, 4, 1, 5, 9, 2, 6]
print(sorted(nums))
# [1, 1, 2, 3, 4, 5, 6, 9]

Сортировка по убыванию с reverse=True

Передайте reverse=True, чтобы получить наибольшие значения первыми.

nums = [3, 1, 4, 1, 5, 9, 2, 6]
print(sorted(nums, reverse=True))
# [9, 6, 5, 4, 3, 2, 1, 1]

Метод list.sort()

list.sort() переупорядочивает список на месте и всегда возвращает None. Используйте его, когда исходный порядок вам больше не нужен и вы хотите избежать накладных расходов памяти от второго списка.

Синтаксис:

list.sort(*, key=None, reverse=False)

Параметры идентичны sorted().

Сортировка списка на месте

python— editable, runs on the server

Сортировка по убыванию

python— editable, runs on the server

sort() возвращает None — распространённая ошибка

Частая ошибка — присваивать результат sort() переменной:

fruits = ['banana', 'apple', 'cherry']
result = fruits.sort()   # sort() modifies fruits, returns None
print(result)            # None  ← not the sorted list!
print(fruits)            # ['apple', 'banana', 'cherry']  ← fruits was modified

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

sorted() vs list.sort() — когда что использовать

sorted()list.sort()
ВозвращаетНовый отсортированный списокNone
Исходный списокНе изменяетсяИзменяется на месте
Работает сЛюбым итерируемым объектомТолько со списками
ПамятьИспользует дополнительную памятьБез дополнительного списка

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

Используйте list.sort(), когда у вас есть список, вы хотите отсортировать его на месте и важна эффективность использования памяти.

Сортировка с параметром key

Параметр key принимает вызываемый объект с одним аргументом. Python вызывает его один раз для каждого элемента и использует возвращённое значение для сравнений. Это позволяет избежать дублирования данных и делает сортировку гибкой.

Сортировка по длине строки

words = ['banana', 'apple', 'cherry', 'kiwi']
print(sorted(words, key=len))
# ['kiwi', 'apple', 'banana', 'cherry']

len передаётся напрямую — lambda не нужна при использовании встроенной функции с одним аргументом.

Сортировка списка кортежей по конкретному полю

python— editable, runs on the server

Lambda lambda x: x[1] извлекает второй элемент (число) из каждого кортежа, чтобы Python сравнивал числа, а не целые кортежи.

Сортировка списка словарей

students = [
    {'name': 'Charlie', 'grade': 85},
    {'name': 'Alice',   'grade': 92},
    {'name': 'Bob',     'grade': 78},
]

by_grade = sorted(students, key=lambda s: s['grade'])
for s in by_grade:
    print(s['name'], s['grade'])
# Bob 78
# Charlie 85
# Alice 92

Для сортировки по убыванию (сначала наивысшая оценка) добавьте reverse=True:

by_grade_desc = sorted(students, key=lambda s: s['grade'], reverse=True)
for s in by_grade_desc:
    print(s['name'], s['grade'])
# Alice 92
# Charlie 85
# Bob 78

Сортировка без учёта регистра

По умолчанию сортировка в Python чувствительна к регистру: все заглавные буквы идут перед строчными, потому что имеют меньшие кодовые точки Unicode. Используйте key=str.lower для сортировки без учёта регистра.

words = ['Banana', 'apple', 'Cherry', 'date']
print(sorted(words))             # case-sensitive (uppercase first)
# ['Banana', 'Cherry', 'apple', 'date']

print(sorted(words, key=str.lower))  # case-insensitive
# ['apple', 'Banana', 'Cherry', 'date']

Использование operator.itemgetter и operator.attrgetter

Модуль operator предоставляет более быстрые альтернативы lambda для распространённых шаблонов ключей.

operator.itemgetter — для последовательностей и словарей

import operator

fruits = [('apple', 10), ('banana', 5), ('cherry', 20)]
print(sorted(fruits, key=operator.itemgetter(1)))
# [('banana', 5), ('apple', 10), ('cherry', 20)]

operator.itemgetter(1) эквивалентен lambda x: x[1], но реализован на C и работает быстрее на больших списках.

operator.attrgetter — для объектов

import operator

class Student:
    def __init__(self, name, grade):
        self.name = name
        self.grade = grade
    def __repr__(self):
        return f'Student({self.name!r}, {self.grade})'

students = [Student('Charlie', 85), Student('Alice', 92), Student('Bob', 78)]
print(sorted(students, key=operator.attrgetter('grade')))
# [Student('Bob', 78), Student('Charlie', 85), Student('Alice', 92)]

Многоключевая сортировка

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

# Sort by grade ascending, then by name alphabetically when grades tie
data = [('Alice', 85), ('Bob', 92), ('Charlie', 85), ('Dave', 78)]
result = sorted(data, key=lambda x: (x[1], x[0]))
print(result)
# [('Dave', 78), ('Alice', 85), ('Charlie', 85), ('Bob', 92)]

У Alice и Charlie одинаковая оценка 85, поэтому они сортируются по алфавиту — Alice перед Charlie.

Стабильность сортировки

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

# Sort by grade, then (stably) by name — same result as the tuple key above
data = [('Alice', 85), ('Bob', 92), ('Charlie', 85), ('Dave', 78)]
step1 = sorted(data, key=lambda x: x[0])   # sort by name first
step2 = sorted(step1, key=lambda x: x[1])  # then sort by grade
print(step2)
# [('Dave', 78), ('Alice', 85), ('Charlie', 85), ('Bob', 92)]

Этот приём — называемый преобразованием Шварца — иногда более читаем, чем составной ключ.

Заключение

sorted() и list.sort() в Python обеспечивают быструю и гибкую сортировку списков с минимальным количеством кода. Используйте sorted(), когда вам нужен новый список или вы сортируете не-списковый итерируемый объект; используйте list.sort(), когда хотите изменить список на месте. Параметр key справляется практически с любым критерием сортировки — от сортировки по длине или полю словаря до сравнений без учёта регистра. Для больших наборов данных предпочитайте operator.itemgetter или operator.attrgetter вместо lambda для лучшей производительности.

Дополнительное чтение:

  • Python Lists — создание списков, индексация и срезы
  • List Methods — полный справочник методов списков
  • List Comprehension — лаконичное создание списков
  • Loop Lists — итерация по спискам

Практика

Практика
Which of the following statements about sorted() and list.sort() are true?
Which of the following statements about sorted() and list.sort() are true?
Was this page helpful?