我教编程这么多年,发现好多同学写排序代码时,总喜欢自己造轮子。一个简单的排序需求,非得写个几十行的比较函数,看着挺唬人,其实特别容易出bug。
有个学生上周找我,说他在处理一个学生成绩排序的问题。要求按成绩从高到低排,成绩相同就按姓名排。他写了将近二十行代码,各种if else嵌套,中间还用了好几个临时列表。我问他为什么不直接用Python的sort函数,他愣了一下,说那个只能排数字啊。
这个误解很常见。Python的sort函数其实有个特别强大的参数叫key,它能让排序变得特别灵活。key接受一个函数,这个函数会作用于每个元素上,排序时按函数返回的值来比较,而不是直接比较元素本身。
拿刚才那个例子来说,假如数据是这样:[('张三', 85), ('李四', 92), ('王五', 85)]。一行代码就能搞定排序:students.sort(key=lambda x: (-x[1], x[0]))。负号代表降序,元组代表多级排序,先按成绩排再按姓名排。简单明了,不容易出错。
还有个更实际的场景。我另一个学生要处理一堆日期字符串,比如'2024-01-15'、'2024-03-02'。如果不处理,直接排序会按字符串字典序排,结果会出错。他打算自己写个比较函数,逐位比较年月日。我跟他说,用key参数,直接转成日期对象就行:dates.sort(key=lambda x: datetime.strptime(x, '%Y-%m-%d'))。一行代码,清晰又可靠。
我见过有些程序员喜欢用sorted配合复杂列表推导式,其实用key参数加上operator模块里的itemgetter、attrgetter,能处理大部分场景。比如按对象属性排序,直接用attrgetter('age')就行,比手写lambda还简洁。很多人不知道这个,白花了不少功夫。
碰到过最夸张的一次,有个项目里排序代码写了近百行,还分了三个函数。我接手后改成两行,一行定义key函数,一行调用sort。原来的写代码的同事看到后,沉默了五分钟,说了句'我以前不知道能用key'。这个同事工作已经三年了。
学会用key参数,排序这件事就能简化很多。你只需要告诉Python按什么规则排,不用关心具体怎么比较。这就像去吃饭,你告诉服务员想吃什么菜就够了,不用自己进厨房炒。生活本来就够复杂了,代码能简单就尽量简单。