Python cmp_to_key函数如何工作?

时间:2013-05-03 15:41:41

标签: python algorithm sorting cmp python-internals

我遇到了这个函数here

我对如何实现这一点感到困惑 - key生成的cmp_to_key函数如何知道给定元素应该是什么“位置”而不检查给定元素与每个元素的比较其他感兴趣的元素?

1 个答案:

答案 0 :(得分:40)

cmp_to_key方法返回一个充当代理键的特殊对象:

class K(object):
    __slots__ = ['obj']
    def __init__(self, obj, *args):
        self.obj = obj
    def __lt__(self, other):
        return mycmp(self.obj, other.obj) < 0
    def __gt__(self, other):
        return mycmp(self.obj, other.obj) > 0
    def __eq__(self, other):
        return mycmp(self.obj, other.obj) == 0
    def __le__(self, other):
        return mycmp(self.obj, other.obj) <= 0
    def __ge__(self, other):
        return mycmp(self.obj, other.obj) >= 0
    def __ne__(self, other):
        return mycmp(self.obj, other.obj) != 0
    def __hash__(self):
        raise TypeError('hash not implemented')

排序时,每个键将与序列中的大多数其他键进行比较。位于0的元素是否低于或大于其他对象?

每当发生这种情况时,都会调用特殊方法挂钩,因此会调用__lt____gt__,而代理键会转而调用cmp方法。

因此列表[1, 2, 3]的排序方式为[K(1), K(2), K(3)],如果K(1)K(2)进行比较以查看K(1)是否更低,那么调用K(1).__lt__(K(2)),将其翻译为mycmp(1, 2) < 0

这就是旧的cmp方法无论如何;返回-1,0或1,具体取决于第一个参数是否小于,等于或大于第二个参数。代理键将这些数字转换回比较运算符的布尔值。

代理键在任何时候都不需要知道关于绝对位置的任何信息。它只需要知道与之比较的一个其他对象,并且特殊方法钩子提供其他对象。