Python自定义排序:多属性类对象的便捷排序实现问询
嘿,这个需求我太懂了——不想搞全局开关那种容易出bug的玩意儿,对吧?给你几个实用又优雅的方案,直接解决按任意属性排序的问题:
方案一:用
operator.attrgetter直接指定排序键 这是最简便高效的方法,完全不用修改你的类代码,直接利用Python标准库的工具就能搞定。operator.attrgetter可以直接提取对象的指定属性作为排序键,比自己写lambda表达式更高效,尤其是属性数量多的时候。
先给你看完整示例:
import operator class MyClass: def __init__(self, a, b, c, d, e): self.a = a self.b = b self.c = c self.d = d self.e = e def __repr__(self): return f"MyClass(a={self.a}, b={self.b}, c={self.c}, d={self.d}, e={self.e})" # 创建实例列表 items = [ MyClass(3, 1, 5, 2, 4), MyClass(1, 4, 2, 5, 3), MyClass(2, 3, 4, 1, 5) ] # 按属性a升序排序 items.sort(key=operator.attrgetter('a')) print("按a排序结果:", items) # 按属性d降序排序 items.sort(key=operator.attrgetter('d'), reverse=True) print("按d降序排序结果:", items)
想用哪个属性排序,直接把attrgetter里的字符串换成对应属性名就行,还能通过reverse=True实现降序,非常灵活。
方案二:给类添加带校验的排序键方法
如果担心不小心传入不存在的属性名,可以给类加一个专门的方法来返回排序键,同时做属性合法性校验:
class MyClass: def __init__(self, a, b, c, d, e): self.a = a self.b = b self.c = c self.d = d self.e = e def __repr__(self): return f"MyClass(a={self.a}, b={self.b}, c={self.c}, d={self.d}, e={self.e})" def get_sort_key(self, attr_name): # 校验属性是否存在 if not hasattr(self, attr_name): raise ValueError(f"类MyClass不存在属性:{attr_name}") return getattr(self, attr_name)
排序的时候用lambda调用这个方法就行:
# 按属性b排序 items.sort(key=lambda x: x.get_sort_key('b'))
这个方案更安全,能提前发现错误的属性名。
方案三:动态生成专属排序方法(进阶玩法)
如果你的代码经常需要按固定属性排序,可以给类动态生成sort_by_xxx这样的静态方法,调用起来更直观:
import operator class MyClass: def __init__(self, a, b, c, d, e): self.a = a self.b = b self.c = c self.d = d self.e = e def __repr__(self): return f"MyClass(a={self.a}, b={self.b}, c={self.c}, d={self.d}, e={self.e})" # 循环生成sort_by_a、sort_by_b等静态方法 for attr in ['a', 'b', 'c', 'd', 'e']: def make_sort_method(target_attr): def sort_method(items, reverse=False): items.sort(key=operator.attrgetter(target_attr), reverse=reverse) return sort_method setattr(MyClass, f"sort_by_{attr}", make_sort_method(attr))
用的时候直接调用类方法就行:
# 按属性c升序排序 MyClass.sort_by_c(items) # 按属性e降序排序 MyClass.sort_by_e(items, reverse=True)
这个方案适合频繁按特定属性排序的场景,代码可读性拉满。
总的来说,最推荐方案一,简洁高效还不用改类;如果需要安全性选方案二;如果追求极致可读性选方案三,按需挑就行~
内容的提问来源于stack exchange,提问作者Semi-Noob117
相关产品推荐
相关产品推荐

