python对复杂对象排序需通过key参数指定规则:可用lambda提取属性、operator.attrgetter高效获取属性(支持多级和多字段)、自定义函数处理复杂逻辑;sorted()返回新列表,sort()原地修改;字典和命名元组也适用。

如果您需要对包含多个属性的自定义类实例或字典等复杂对象进行排序,Python内置的sort()方法和sorted()函数默认无法直接比较,必须通过key参数指定提取排序依据的规则。以下是实现该目标的具体方式:
一、使用lambda表达式作为key参数
lambda表达式可快速定义匿名函数,用于从每个对象中提取用于比较的单一值,如属性名、索引或计算结果。
1、定义一个包含name和age属性的Person类,并创建若干实例组成的列表。
2、调用list.sort(key=lambda x: x.age)对列表原地升序排序,依据每个对象的age属性值。
立即学习“Python免费学习笔记(深入)”;
3、若需降序,添加reverse=True参数:list.sort(key=lambda x: x.age, reverse=True)。
4、对字典列表排序时,使用key=lambda d: d['score']提取字典中'score'键对应的值。
二、使用operator.attrgetter提取对象属性
operator.attrgetter是专门用于获取对象属性的高效工具,比lambda更简洁且支持多级属性访问与元组形式的多字段排序。
1、导入模块:from operator import attrgetter。
2、对Person对象列表按age排序:people.sort(key=attrgetter('age'))。
3、按name升序、age降序组合排序:people.sort(key=attrgetter('name', '-age'))。
4、访问嵌套属性如person.address.city:key=attrgetter('address.city')。
三、使用自定义函数作为key参数
当排序逻辑较复杂(如忽略大小写、按中文拼音、处理缺失值等),可定义具名函数,提高可读性与复用性。
1、定义函数def get_sort_key(obj): return obj.name.lower()。
2、调用sorted(data, key=get_sort_key)获得新排序列表。
3、在函数内处理None值:return obj.priority if obj.priority is not None else float('inf')。
4、对字符串长度加权排序:return len(obj.title) * 10 + obj.rating。
四、sorted()与list.sort()的区别应用
sorted()返回新列表,不改变原数据;list.sort()就地修改原列表并返回None,二者均接受key和reverse参数,但适用场景不同。
1、需保留原始顺序时,必须使用sorted(),例如:new_list = sorted(items, key=lambda x: x.id)。
2、对原列表排序后无需旧顺序,使用items.sort(key=lambda x: x.timestamp),避免写成 items = items.sort(),因后者将使items变为None。
3、元组、字典视图等不可变或非列表类型只能用sorted(),如sorted(d.items(), key=lambda t: t[1])按字典值排序。
4、对字符串列表忽略大小写排序:sorted(words, key=str.lower)。
五、处理字典与命名元组的排序
字典本身无序,但其键值对可转为元组序列后排序;命名元组具有类似类的属性访问能力,适合结构化数据排序。
1、对字典按值排序:sorted(my_dict.items(), key=lambda kv: kv[1]),结果为(键, 值)元组列表。
2、使用collections.namedtuple定义Point = namedtuple('Point', ['x', 'y']),然后按x坐标排序:points.sort(key=attrgetter('x'))。
3、字典列表中某字段含空字符串时,用key=lambda d: d.get('code', '')确保不报KeyError。
4、对JSON解析后的嵌套列表排序:data.sort(key=lambda x: x['user']['profile']['level'])。










