当我调试一些不合逻辑的行为时,我在 Python 2.5 sorted() 函数调用中发现了以下怪异之处:
>>> aa = [10, 5, 20]
>>> sorted(range(len(aa)))
[0, 1, 2]
sorted(range(len(aa)), key=lambda a: aa[a])
[1, 0, 2]
sorted(range(len(aa)), key=lambda a: -aa[a])
[2, 0, 1]
前两个调用按预期工作,但最后一个是恕我直言,错误!它应该是:[1, 2, 0]。
在尝试找到问题根源的进一步实验之后,我得出了这个(不使用 lambda 或否定操作,但在其他方面是相同的问题):
>>> bb = [-10, -5, -20]
>>> sorted([0, 1, 2], key=bb.__getitem__)
[2, 0, 1]
即使像下面这样的事情也不起作用并表明双重否定再次起作用:
>>> bb = [-10, -5, -20]
>>> def fun(i):
... return bb[i]
>>> sorted([0, 1, 2], key=fun)
[2, 0, 1]
>>> def fun2(i):
... return -bb[i]
>>> sorted([0, 1, 2], key=fun2)
[1, 0, 2]
我是不是失去了理智或者问题出在哪里?或者为什么 Python 3.x 没有以前工作正常的 cmp 参数(兼容性是我不使用它的原因)?
最佳答案
键函数返回的值充当被排序值的代理。 所以当你说
sorted(range(len(aa)), key=lambda a: -aa[a])
您正在对 range(len(aa)
) 进行排序,即 [0, 1, 2]
,但使用值
-aa[0], -aa[1], -aa[2]
作为代理值。
range(len(aa)) 0 1 2 <-- values
aa[a] 10 5 20
-aa[a] -10 -5 -20 <-- proxy values
因为-20,或者说-aa[2]
,是最小的代理值,它的关联值2
成为排序结果中的第一个元素。
由于 -10 或 -aa[0]
是下一个最小的,因此其关联值 0 成为排序结果中的第二个元素。
最后-5,即-aa[1]
是最后一个值,所以1是排序结果中的最后一个数。
因此,sorted(range(len(aa)), key=lambda a: -aa[a])
等于 [2, 0, 1]
。
Python 给出的答案是正确的。
关于Python sorted() 关键函数怪异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4115636/