5 эффективных методов сортировки списков в Python для разработчиков
Для кого эта статья:
- Начинающие и опытные Python-разработчики
- Студенты и обучающиеся программированию
Практикующие разработчики, желающие улучшить навыки работы с сортировкой данных
Сортировка списков — это базовый навык, который должен быть в арсенале каждого Python-разработчика. Правильно выбранный метод сортировки может радикально улучшить производительность вашего кода и сделать его более элегантным. Будь то простое упорядочивание чисел или сложная сортировка объектов по нескольким критериям — Python предлагает мощные инструменты для любой задачи. В этой статье мы разберем пять проверенных методов сортировки списков, которые помогут вам писать более эффективный код 🚀
Хотите уверенно применять продвинутые методы сортировки в своих проектах? На курсе Обучение Python-разработке от Skypro вы получите не только теоретические знания, но и практические навыки работы со структурами данных под руководством опытных разработчиков. Наши студенты начинают применять изученные алгоритмы сортировки уже со второй недели обучения, создавая реальные проекты для своего портфолио.
Основные методы сортировки списков в Python
Python предлагает несколько элегантных способов сортировки данных, каждый из которых имеет свои преимущества в определенных ситуациях. Рассмотрим пять основных методов, которые должен знать каждый разработчик.
Сортировка в Python реализована на основе алгоритма Timsort — гибридного алгоритма, который объединяет преимущества сортировки слиянием (merge sort) и сортировки вставками (insertion sort). Это обеспечивает высокую производительность для различных типов данных и паттернов.
| Метод | Изменяет исходный список | Возвращает значение | Особенности |
|---|---|---|---|
| list.sort() | Да | None | Работает только со списками |
| sorted() | Нет | Новый отсортированный список | Работает с любыми итерируемыми объектами |
| lambda с sort()/sorted() | Зависит от метода | Зависит от метода | Позволяет задать сложные критерии сортировки |
| itemgetter/attrgetter | Зависит от метода | Зависит от метода | Более эффективны для сортировки по ключам |
| Кастомные функции сортировки | Зависит от реализации | Зависит от реализации | Максимальная гибкость для сложных случаев |
Михаил Петров, Python-разработчик в финтех компании
Помню свой первый проект анализа данных для клиента из банковской сферы. Нужно было обработать массив транзакций и отсортировать их по нескольким критериям. Я использовал вложенные циклы и самописные функции сравнения — код работал, но медленно. Старший разработчик указал на неоптимальность моего подхода и показал, как решить задачу в одну строку с помощью sorted() и lambda-функции для сортировки по нескольким полям. Производительность возросла в разы, а клиент получил результаты на день раньше срока. С тех пор я всегда начинаю с базовых методов Python для сортировки, прежде чем придумывать собственный велосипед.
Давайте разберем каждый метод более подробно, чтобы вы могли выбрать оптимальный инструмент для своих задач. 📊

Встроенный метод sort(): изменение исходного списка
Метод list.sort() — самый простой и часто используемый способ сортировки списков в Python. Его ключевая особенность в том, что он модифицирует исходный список напрямую, не создавая копий. Это делает его более эффективным по памяти, но требует осторожности, если вам нужно сохранить оригинальный порядок элементов.
Базовый синтаксис метода прост:
my_list = [3, 1, 4, 1, 5, 9, 2, 6]
my_list.sort()
print(my_list) # [1, 1, 2, 3, 4, 5, 6, 9]
Для сортировки в обратном порядке используйте параметр reverse=True:
my_list = [3, 1, 4, 1, 5, 9, 2, 6]
my_list.sort(reverse=True)
print(my_list) # [9, 6, 5, 4, 3, 2, 1, 1]
Особенности метода sort(), которые важно учитывать:
- Метод возвращает
None, а не отсортированный список — распространенная ошибка новичков состоит в попытке присвоить результат переменной. - Работает только со списками — если вам нужно отсортировать кортеж или другой итерируемый объект, придется использовать
sorted(). - Изменяет исходный список — это может быть как преимуществом (экономия памяти), так и недостатком (потеря исходного порядка).
Вот пример распространенной ошибки, которую следует избегать:
my_list = [3, 1, 4, 1, 5, 9, 2, 6]
sorted_list = my_list.sort() # Ошибка! sort() возвращает None
print(sorted_list) # None
Правильный подход, если вам нужно сохранить как исходный, так и отсортированный список:
my_list = [3, 1, 4, 1, 5, 9, 2, 6]
sorted_list = my_list.copy() # Создаем копию
sorted_list.sort() # Сортируем копию
print(my_list) # [3, 1, 4, 1, 5, 9, 2, 6] – оригинал не изменился
print(sorted_list) # [1, 1, 2, 3, 4, 5, 6, 9] – отсортированная копия
Метод sort() особенно полезен, когда вы работаете с большими объемами данных и хотите минимизировать использование памяти, или когда исходный порядок вам больше не нужен. 🔄
Функция sorted(): создание нового отсортированного списка
В отличие от метода sort(), функция sorted() не изменяет исходный объект, а возвращает новый отсортированный список. Это делает её более универсальной и безопасной для использования в ситуациях, когда важно сохранить исходный порядок элементов.
Базовый синтаксис функции:
original_list = [3, 1, 4, 1, 5, 9, 2, 6]
sorted_list = sorted(original_list)
print(original_list) # [3, 1, 4, 1, 5, 9, 2, 6] – исходный список не изменился
print(sorted_list) # [1, 1, 2, 3, 4, 5, 6, 9] – новый отсортированный список
Функция sorted() также принимает параметр reverse для сортировки в обратном порядке:
original_list = [3, 1, 4, 1, 5, 9, 2, 6]
sorted_list = sorted(original_list, reverse=True)
print(sorted_list) # [9, 6, 5, 4, 3, 2, 1, 1]
Ключевые преимущества функции sorted():
- Работает с любыми итерируемыми объектами (списками, кортежами, строками, множествами, словарями и т.д.)
- Сохраняет оригинальную коллекцию неизменной
- Возвращает список независимо от типа входных данных
Вот несколько примеров использования sorted() с различными типами данных:
# Сортировка кортежа
tuple_data = (3, 1, 4, 1, 5, 9, 2, 6)
sorted_tuple = sorted(tuple_data) # Возвращает список
print(sorted_tuple) # [1, 1, 2, 3, 4, 5, 6, 9]
# Сортировка строки
string_data = "python"
sorted_string = sorted(string_data) # Возвращает список символов
print(sorted_string) # ['h', 'n', 'o', 'p', 't', 'y']
print(''.join(sorted_string)) # "hnopty"
# Сортировка словаря (сортируются ключи)
dict_data = {'c': 3, 'a': 1, 'b': 2}
sorted_keys = sorted(dict_data)
print(sorted_keys) # ['a', 'b', 'c']
# Для сортировки по значениям словаря:
sorted_by_values = sorted(dict_data.items(), key=lambda x: x[1])
print(sorted_by_values) # [('a', 1), ('b', 2), ('c', 3)]
Анна Соколова, преподаватель программирования
На одном из моих курсов для начинающих разработчиков мы работали с задачей анализа текстовых данных. Студенты должны были обрабатывать отзывы пользователей и ранжировать их по различным параметрам. Большинство студентов правильно использовали функцию sorted() для этой задачи, но один из них постоянно жаловался, что его код "ломает данные" — исходные отзывы меняли порядок после сортировки. Когда я посмотрела его код, обнаружилось, что он использовал метод list.sort() вместо sorted(), не понимая разницы между ними. После объяснения и замены метода проблема была решена. Теперь я всегда начинаю тему сортировки с четкого разграничения этих двух подходов, что помогает студентам избежать подобных ошибок.
Функция sorted() особенно полезна в функциональном программировании, когда мы стремимся к неизменяемости данных, и в ситуациях, когда требуется сохранить исходные данные для последующей обработки или отладки. 🔍
Сортировка по ключу: настройка критериев упорядочивания
Параметр key в методах сортировки — это мощный инструмент, который позволяет определить, по какому критерию будут сравниваться элементы списка. Он принимает функцию, которая применяется к каждому элементу перед сравнением, что открывает огромные возможности для кастомизации процесса сортировки.
Базовый синтаксис использования параметра key:
# С методом sort()
my_list.sort(key=function_name)
# С функцией sorted()
sorted_list = sorted(my_list, key=function_name)
Где function_name — функция, которая принимает элемент списка и возвращает значение для сравнения.
Рассмотрим несколько практических примеров:
1. Сортировка строк без учета регистра
names = ["Alice", "bob", "Charlie", "david"]
sorted_names = sorted(names, key=str.lower)
print(sorted_names) # ["Alice", "bob", "Charlie", "david"]
2. Сортировка по длине строк
words = ["python", "is", "an", "awesome", "language"]
sorted_by_length = sorted(words, key=len)
print(sorted_by_length) # ["is", "an", "python", "awesome", "language"]
3. Сортировка по последнему символу строки
words = ["python", "javascript", "ruby", "go"]
sorted_by_last_char = sorted(words, key=lambda x: x[-1])
print(sorted_by_last_char) # ["go", "ruby", "javascript", "python"]
4. Сортировка списка кортежей по второму элементу
data = [(1, 5), (3, 2), (2, 8), (4, 1)]
sorted_data = sorted(data, key=lambda x: x[1])
print(sorted_data) # [(4, 1), (3, 2), (1, 5), (2, 8)]
5. Сортировка списка словарей по значению определённого ключа
students = [
{"name": "Alice", "grade": 85},
{"name": "Bob", "grade": 92},
{"name": "Charlie", "grade": 78}
]
sorted_students = sorted(students, key=lambda x: x["grade"], reverse=True)
print(sorted_students)
# [{"name": "Bob", "grade": 92}, {"name": "Alice", "grade": 85}, {"name": "Charlie", "grade": 78}]
Для более сложных случаев сортировки Python предлагает модуль operator, который содержит полезные функции itemgetter и attrgetter:
import operator
# Сортировка списка кортежей по нескольким элементам
data = [("Alice", 25, "Engineer"), ("Bob", 25, "Designer"), ("Charlie", 30, "Manager")]
sorted_data = sorted(data, key=operator.itemgetter(1, 0)) # Сначала по возрасту, затем по имени
print(sorted_data)
# [("Alice", 25, "Engineer"), ("Bob", 25, "Designer"), ("Charlie", 30, "Manager")]
# Сортировка списка объектов по атрибуту
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f"Person({self.name}, {self.age})"
people = [Person("Alice", 25), Person("Bob", 30), Person("Charlie", 20)]
sorted_people = sorted(people, key=operator.attrgetter("age"))
print(sorted_people)
# [Person(Charlie, 20), Person(Alice, 25), Person(Bob, 30)]
| Подход к ключу сортировки | Преимущества | Недостатки | Когда использовать |
|---|---|---|---|
| Lambda-функции | Краткость, удобство для простых преобразований | Менее читаемы для сложных преобразований | Для простых, одноразовых критериев сортировки |
| itemgetter/attrgetter | Более эффективны чем lambda, лаконичный синтаксис | Требуют импорта модуля operator | Для сортировки по элементам коллекций/атрибутам объектов |
| Именованные функции | Высокая читаемость, возможность переиспользования | Больше кода для простых случаев | Для сложной логики сортировки, используемой многократно |
| Методы объектов | Встроенные методы оптимизированы и читаемы | Ограничены функциональностью существующих методов | Для стандартных операций (напр., str.lower для case-insensitive) |
Параметр key — это то, что делает методы сортировки в Python невероятно гибкими. Он позволяет адаптировать сортировку под любые, даже самые специфические требования, сохраняя при этом эффективность встроенных алгоритмов. 🔑
Продвинутые техники сортировки сложных структур данных
Для решения более сложных задач сортировки Python предлагает ряд продвинутых техник, которые позволяют обрабатывать многомерные структуры данных, осуществлять сортировку по нескольким критериям и даже создавать кастомные порядки сортировки.
1. Сортировка по нескольким критериям Для сортировки по нескольким полям вы можете вернуть кортеж из функции key:
data = [
{"name": "Alice", "age": 30, "salary": 75000},
{"name": "Bob", "age": 25, "salary": 65000},
{"name": "Charlie", "age": 30, "salary": 80000},
{"name": "Dave", "age": 25, "salary": 65000}
]
# Сортировка сначала по возрасту (по возрастанию), затем по зарплате (по убыванию), затем по имени
sorted_data = sorted(data, key=lambda x: (x["age"], -x["salary"], x["name"]))
for item in sorted_data:
print(item)
# {'name': 'Dave', 'age': 25, 'salary': 65000}
# {'name': 'Bob', 'age': 25, 'salary': 65000}
# {'name': 'Charlie', 'age': 30, 'salary': 80000}
# {'name': 'Alice', 'age': 30, 'salary': 75000}
Обратите внимание на использование отрицательного значения для сортировки зарплаты по убыванию. Это работает только для числовых значений. Для строк можно использовать подход с reverse параметром для каждого ключа:
from operator import itemgetter
# Функция для сортировки по нескольким ключам с разным порядком
def multisort(items, specs):
for key, reverse in reversed(specs):
items.sort(key=itemgetter(key), reverse=reverse)
return items
# Пример использования: сортировка по возрасту (возрастание), затем по имени (убывание)
multisort(data[:], [('age', False), ('name', True)])
2. Кастомная логика сравнения с functools.cmp_to_key
В Python 2 существовал параметр cmp, который позволял задать функцию сравнения двух элементов. В Python 3 его заменили на key, но вы все еще можете использовать функцию сравнения через functools.cmp_to_key:
import functools
# Кастомный порядок сортировки игральных карт
def compare_cards(card1, card2):
suits_order = {'Spades': 0, 'Hearts': 1, 'Diamonds': 2, 'Clubs': 3}
ranks_order = {'Ace': 0, 'King': 1, 'Queen': 2, 'Jack': 3, '10': 4, '9': 5, '8': 6, '7': 7}
# Сначала сравниваем масти
suit_diff = suits_order[card1[1]] – suits_order[card2[1]]
if suit_diff != 0:
return suit_diff
# Если масти одинаковые, сравниваем ранги
return ranks_order[card1[0]] – ranks_order[card2[0]]
cards = [
('King', 'Hearts'), ('Ace', 'Spades'), ('10', 'Diamonds'),
('Jack', 'Clubs'), ('Ace', 'Hearts'), ('9', 'Spades')
]
sorted_cards = sorted(cards, key=functools.cmp_to_key(compare_cards))
print(sorted_cards)
# [('Ace', 'Spades'), ('9', 'Spades'), ('Ace', 'Hearts'), ('King', 'Hearts'), ('10', 'Diamonds'), ('Jack', 'Clubs')]
3. Стабильная сортировка и ее применение Сортировка в Python является стабильной, что означает, что элементы с одинаковыми ключами сортировки сохранят свой относительный порядок. Это позволяет эффективно реализовать пошаговую сортировку:
# Данные: (имя, отдел, зарплата)
employees = [
("Alice", "Engineering", 85000),
("Bob", "Sales", 75000),
("Charlie", "Engineering", 70000),
("David", "Marketing", 65000),
("Eva", "Sales", 90000)
]
# Сначала сортируем по зарплате (от высокой к низкой)
by_salary = sorted(employees, key=lambda x: x[2], reverse=True)
# Затем сортируем по отделу, сохраняя порядок зарплат внутри отдела
by_dept_and_salary = sorted(by_salary, key=lambda x: x[1])
for emp in by_dept_and_salary:
print(f"{emp[0]} ({emp[1]}): ${emp[2]}")
# Charlie (Engineering): $70000
# Alice (Engineering): $85000
# David (Marketing): $65000
# Eva (Sales): $90000
# Bob (Sales): $75000
4. Эффективная сортировка больших объемов данных При работе с большими наборами данных важна эффективность. Вот несколько советов:
- Используйте
operator.itemgetterиoperator.attrgetterвместо lambda-функций для повышения производительности. - Предварительно вычислите и кешируйте ключи сортировки, если их вычисление дорого.
- Для очень больших наборов данных рассмотрите использование внешних сортировок или специализированных библиотек, таких как NumPy или Pandas.
import operator
from functools import lru_cache
@lru_cache(maxsize=None)
def expensive_computation(item):
# Предположим, это дорогостоящее вычисление
return some_complex_function(item)
# Использование кешированной функции как ключа
sorted_items = sorted(large_data_set, key=expensive_computation)
# Или используйте предварительное вычисление
key_value_pairs = [(expensive_computation(item), item) for item in large_data_set]
key_value_pairs.sort()
sorted_items = [item for _, item in key_value_pairs]
5. Сортировка вложенных структур данных Для сортировки многомерных структур используйте вложенные функции доступа:
# Список списков: [имя, [результаты тестов], средний балл]
students = [
["Alice", [85, 90, 92], 89],
["Bob", [75, 80, 85], 80],
["Charlie", [95, 85, 80], 86.7],
["David", [70, 75, 80], 75]
]
# Сортировка по второму тесту
sorted_by_second_test = sorted(students, key=lambda x: x[1][1])
print(sorted_by_second_test)
# [["David", [70, 75, 80], 75], ["Bob", [75, 80, 85], 80], ["Charlie", [95, 85, 80], 86.7], ["Alice", [85, 90, 92], 89]]
# Более сложный пример: массив JSON-подобных объектов
data = [
{"user": {"name": "Alice", "id": 123}, "stats": {"posts": 25, "likes": 150}},
{"user": {"name": "Bob", "id": 456}, "stats": {"posts": 10, "likes": 200}},
{"user": {"name": "Charlie", "id": 789}, "stats": {"posts": 30, "likes": 120}}
]
# Сортировка по количеству лайков
sorted_by_likes = sorted(data, key=lambda x: x["stats"]["likes"], reverse=True)
for item in sorted_by_likes:
print(f"{item['user']['name']}: {item['stats']['likes']} likes")
# Bob: 200 likes
# Alice: 150 likes
# Charlie: 120 likes
Освоение этих продвинутых техник сортировки позволит вам эффективно работать с самыми сложными структурами данных и решать нетривиальные задачи упорядочивания информации. 📈
Владение различными методами сортировки в Python — это не просто техническое умение, а стратегическое преимущество. Выбор правильного подхода может значительно повысить производительность вашего кода и улучшить его читаемость. От простого метода sort() для базовых списков до продвинутых техник с использованием operator.itemgetter и функций-компараторов — каждый инструмент имеет свою область применения. Не бойтесь экспериментировать и комбинировать различные подходы для решения нестандартных задач сортировки.
Читайте также
- Срезы списков Python: от базовых до продвинутых техник работы с данными
- Поиск в списках Python: методы index() и count() для разработчиков
- 5 эффективных методов поиска элементов в списках Python: обзор
- Структуры данных в Python: коллекции для эффективного кода
- Python метод reverse(): изменение порядка элементов списка эффективно
- Python метод insert(): вставка элементов в список на нужную позицию
- Списки в Python: мощный инструмент для эффективной разработки
- Метод count() в Python: подсчет элементов в списках, строках, кортежах
- Метод index() в Python: поиск элементов в списках, строках, кортежах
- 5 способов очистки списков в Python: что работает эффективнее


