5 эффективных методов сортировки списков в Python для разработчиков
#Основы Python #Списки, кортежи, множества #АлгоритмыДля кого эта статья:
- Начинающие и опытные Python-разработчики
- Студенты и обучающиеся программированию
Практикующие разработчики, желающие улучшить навыки работы с сортировкой данных
Сортировка списков — это базовый навык, который должен быть в арсенале каждого Python-разработчика. Правильно выбранный метод сортировки может радикально улучшить производительность вашего кода и сделать его более элегантным. Будь то простое упорядочивание чисел или сложная сортировка объектов по нескольким критериям — Python предлагает мощные инструменты для любой задачи. В этой статье мы разберем пять проверенных методов сортировки списков, которые помогут вам писать более эффективный код 🚀
Основные методы сортировки списков в 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 и функций-компараторов — каждый инструмент имеет свою область применения. Не бойтесь экспериментировать и комбинировать различные подходы для решения нестандартных задач сортировки.
Читайте также
Таисия Ермакова
backend-разработчик