На этом шаге мы рассмотрим один из способов решения этой задачи.
Вы хотите отсортировать объекты одного класса, но они не поддерживают операции сравнения.
Встроенная функция sorted() принимает аргумент key, в котором может быть передан вызываемый объект, который будет возвращать некоторое значение из объектов, которое sorted() будет использовать для сравнения этих объектов. Например, если у вас в приложении есть последовательность экземпляров класса User и вы хотите отсортировать их по атрибуту user_id, то вы могли бы предоставить вызываемый объект, который принимает экземпляр класса User и возвращает атрибут user_id. Например:
>>> class User: def __init__(self, user_id): self.user_id = user_id def __repr__(self): return 'User({})'.format(self.user_id) >>> users = [User(23), User(3), User(99)] >>> users [User(23), User(3), User(99)] >>> sorted(users, key=lambda u: u.user_id) [User(3), User(23), User(99)] >>>
Вместо lambda можно применить альтернативный подход с использованием operator.attrgetter():
>>> from operator import attrgetter >>> sorted(users, key=attrgetter('user_id')) [User(3), User(23), User(99)] >>>
Использовать или не использовать lambda или attrgetter() - вопрос личных предпочтений. Однако attrgetter() часто оказывается немного быстрее, а также позволяет одновременно извлекать несколько полей. Это аналогично использованию operator.itemgetter() для словарей. Например, если экземпляры класса User также имеют атрибуты first_name и last_name, вы можете выполнить вот такую сортировку:
by_name = sorted(users, key=attrgetter('last_name', 'first_name'
Стоит отметить, что использованный в этом рецепте прием может быть применен к таким функциям, как min() и max(). Например:
>>> min(users, key=attrgetter('user_id')) User(3) >>> max(users, key=attrgetter('user_id')) User(99) >>>
На следующем шаге мы рассмотрим группирование записей на основе полей.