Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Назначение ключей (key) в функциях работы со списками
Параметр key в функциях сортировки и поиска позволяет задать критерий, по которому сравниваются элементы, не изменяя сами элементы. Это один из самых мощных инструментов Python для работы со списками.
Основной концепт
Проблема
# Нужно отсортировать студентов по имени
students = [("Alice", 25), ("Bob", 20), ("Charlie", 23)]
# Без key: сортирует по первому элементу кортежа
sorted_students = sorted(students)
print(sorted_students)
# [('Alice', 25), ('Bob', 20), ('Charlie', 23)]
# Работает, но по алфавиту имён
# Нужно отсортировать по возрасту (второй элемент)
# Как это сделать? 👇
Решение: key parameter
students = [("Alice", 25), ("Bob", 20), ("Charlie", 23)]
# Указываем функцию, которая извлекает значение для сравнения
sorted_by_age = sorted(students, key=lambda x: x[1])
print(sorted_by_age)
# [('Bob', 20), ('Charlie', 23), ('Alice', 25)]
# Отсортировано по возрасту!
Где используется key
1. sorted() — сортировка
# Пример 1: сортировка строк по длине
words = ["apple", "pie", "python", "code"]
sorted_by_length = sorted(words, key=len)
print(sorted_by_length)
# ['pie', 'code', 'apple', 'python']
# Пример 2: сортировка словарей по значению
users = [
{"name": "Alice", "score": 85},
{"name": "Bob", "score": 92},
{"name": "Charlie", "score": 78},
]
sorted_by_score = sorted(users, key=lambda user: user['score'], reverse=True)
print(sorted_by_score)
# [{"name": "Bob", "score": 92}, ...]
# Пример 3: естественная сортировка файлов
files = ["file1.txt", "file10.txt", "file2.txt"]
# Неправильно (лексикографическая сортировка)
wrong_sort = sorted(files)
print(wrong_sort)
# ['file1.txt', 'file10.txt', 'file2.txt']
# Правильно (естественная сортировка)
import re
def natural_sort_key(text):
return [int(c) if c.isdigit() else c for c in re.split(r'(\d+)', text)]
correct_sort = sorted(files, key=natural_sort_key)
print(correct_sort)
# ['file1.txt', 'file2.txt', 'file10.txt']
2. list.sort() — сортировка на месте
# sorted() возвращает новый список
# list.sort() изменяет список на месте (экономит память)
scores = [5, 2, 8, 1, 9]
scores.sort() # Изменяет список на месте
print(scores) # [1, 2, 5, 8, 9]
scores.sort(reverse=True) # По убыванию
print(scores) # [9, 8, 5, 2, 1]
# С key
products = [
{"name": "Laptop", "price": 1200},
{"name": "Mouse", "price": 20},
{"name": "Monitor", "price": 300},
]
products.sort(key=lambda p: p['price'])
for product in products:
print(f"{product['name']}: ${product['price']}")
# Mouse: $20
# Monitor: $300
# Laptop: $1200
3. max() и min() — поиск максимума/минимума
# Найти студента с наибольшей оценкой
students = [
{"name": "Alice", "score": 85},
{"name": "Bob", "score": 92},
{"name": "Charlie", "score": 78},
]
top_student = max(students, key=lambda s: s['score'])
print(f"Top student: {top_student['name']} with score {top_student['score']}")
# Top student: Bob with score 92
# Найти слово с максимальной длиной
words = ["python", "programming", "code", "development"]
longest = max(words, key=len)
print(f"Longest word: {longest}")
# Longest word: development
# Найти продукт с минимальной ценой
products = [
{"name": "Laptop", "price": 1200},
{"name": "Mouse", "price": 20},
{"name": "Monitor", "price": 300},
]
cheapest = min(products, key=lambda p: p['price'])
print(f"Cheapest: {cheapest['name']} at ${cheapest['price']}")
# Cheapest: Mouse at $20
4. Встроенная функция в sorted
# sorted() использует key для каждого элемента
# Сортировка по нескольким критериям
students = [
{"name": "Alice", "grade": "A", "score": 85},
{"name": "Bob", "grade": "A", "score": 92},
{"name": "Charlie", "grade": "B", "score": 88},
]
# Сначала по оценке, потом по баллам
sorted_students = sorted(
students,
key=lambda s: (s['grade'], -s['score']) # Кортеж как ключ
)
for student in sorted_students:
print(f"{student['name']}: {student['grade']} ({student['score']})")
# Bob: A (92)
# Alice: A (85)
# Charlie: B (88)
Практические примеры
Пример 1: Сортировка объектов из БД
from dataclasses import dataclass
from datetime import datetime
@dataclass
class Post:
id: int
title: str
created_at: datetime
likes: int
posts = [
Post(1, "Python Tips", datetime(2024, 1, 15), 50),
Post(2, "Django Tutorial", datetime(2024, 2, 10), 120),
Post(3, "FastAPI Guide", datetime(2024, 1, 20), 85),
]
# Сортировка по дате (новые сверху)
recent_posts = sorted(posts, key=lambda p: p.created_at, reverse=True)
for post in recent_posts:
print(f"{post.title} ({post.created_at.date()})")
# Django Tutorial (2024-02-10)
# FastAPI Guide (2024-01-20)
# Python Tips (2024-01-15)
# Сортировка по лайкам
popular_posts = sorted(posts, key=lambda p: p.likes, reverse=True)
for post in popular_posts:
print(f"{post.title} ({post.likes} likes)")
# Django Tutorial (120 likes)
# FastAPI Guide (85 likes)
# Python Tips (50 likes)
Пример 2: Кейс-инсензитивная сортировка
# Проблема: обычная сортировка регистрозависима
names = ["alice", "Bob", "charlie", "David"]
wrong_sort = sorted(names)
print(wrong_sort)
# ['Bob', 'David', 'alice', 'charlie'] # Заглавные первыми!
# Решение: используйте key=str.lower
correct_sort = sorted(names, key=str.lower)
print(correct_sort)
# ['alice', 'Bob', 'charlie', 'David'] # Правильно!
Пример 3: Сортировка с преобразованием
# Сортировка ISO дат как строк
date_strings = ["2024-03-15", "2024-01-10", "2024-02-20"]
# Неправильно (как строки)
wrong = sorted(date_strings)
print(wrong)
# ['2024-01-10', '2024-02-20', '2024-03-15'] # Работает, но медленно
# Правильно (используем key для преобразования)
from datetime import datetime
correct = sorted(
date_strings,
key=lambda d: datetime.strptime(d, '%Y-%m-%d')
)
print(correct)
# ['2024-01-10', '2024-02-20', '2024-03-15']
Пример 4: Сортировка по методу класса
class User:
def __init__(self, name, age):
self.name = name
self.age = age
def get_priority(self):
# VIP if age > 50
return 0 if self.age > 50 else 1
def __repr__(self):
return f"User({self.name}, {self.age})"
users = [
User("Alice", 30),
User("Bob", 55),
User("Charlie", 28),
User("David", 60),
]
# Сортировка по методу
vip_first = sorted(users, key=lambda u: u.get_priority())
for user in vip_first:
print(user)
# User(Bob, 55)
# User(David, 60)
# User(Alice, 30)
# User(Charlie, 28)
Пример 5: Сложная сортировка для поиска
from operator import itemgetter, attrgetter
# Способ 1: через lambda
data = [
{"category": "A", "priority": 1, "name": "Task 1"},
{"category": "B", "priority": 2, "name": "Task 2"},
{"category": "A", "priority": 3, "name": "Task 3"},
]
sorted_data = sorted(
data,
key=lambda x: (x['category'], x['priority'])
)
# Способ 2: через itemgetter (быстрее!)
sorted_data = sorted(data, key=itemgetter('category', 'priority'))
for item in sorted_data:
print(f"{item['category']}-{item['priority']}: {item['name']}")
# A-1: Task 1
# A-3: Task 3
# B-2: Task 2
Производительность
import timeit
data = list(range(10000, 0, -1))
# Lambda
t1 = timeit.timeit(
lambda: sorted(data, key=lambda x: -x),
number=100
)
# operator.itemgetter (быстрее для simple extraction)
t2 = timeit.timeit(
lambda: sorted(data, key=lambda x: -x),
number=100
)
print(f"Lambda: {t1:.4f}s")
print(f"Itemgetter: {t2:.4f}s")
# itemgetter обычно быстрее на 20-30% для простых операций
Лучшие практики
# ✅ Используйте key для:
# - Сортировки по полям объектов
# - Кейс-инсензитивной сортировки
# - Сортировки по производным значениям
# - Поиска max/min по критерию
# ❌ Не делайте:
# - Не сортируйте внутри key (будет медленно)
# - Не вызывайте дорогие функции в key
# - Не используйте side effects в key
# Плохо
bad_key = lambda x: do_expensive_calculation(x)
# Хорошо
good_key = lambda x: x.field # Простое извлечение значения
Вывод
Параметр key — это мощный механизм для определения критериев сравнения в Python. Правильное использование key делает код:
- Более читаемым
- Более гибким
- Более производительным
Это essential skill для написания clean и efficient Python кода при работе со списками и поиском.