问题描述
你想排序类型相同的对象,但是它们不支持原生的比较操作。
解决方案
内置函数sorted()
有一个关键字参数key
,可以传入一个callable
对象给它,这个callable
对象对每个传入的对象返回一个值,这个值会被sorted
用来排序这些对象。
比如有一个User
实例序列,你希望通过它们的user_id
属性排序,那么你可以提供一个以User
实例为输入,对应的user_id
为输出的callable
对象。比如如下的lambda
函数:
class User:
def __init__(self, user_id):
self.user_id = user_id
def __repr__(self):
return 'User({})'.format(self.user_id)
def sort_users():
users = [User(23), User(3), User(99)]
print(users)
print(sorted(users, key=lambda u: u.user_id))
"""sort_users()输出结果:
[User(23), User(3), User(99)]
[User(3), User(23), User(99)]
"""
也可以用operator.attrgetter()
替代lambda
函数:
from operator import attrgetter
sorted(users, key=attrgetter('user_id'))
讨论
通常attrgetter()
函数运行的更快一些,并且可以支持多字段比较。这个跟operator.itemgetter()
函数作用于字典类型很类似(参考1.13小节)。例如,如果User
实例还有一个name
属性,那么可以像这样排序:sorted(users, key=attrgetter('user_id', 'name'))
。
同样的,这一方法也适用于像min()
和max()
之类的函数。比如:
min(users, key=attrgetter('user_id')) # User(3)
max(users, key=attrgetter('user_id')) # User(99)