为什么在Python3.0中从排序/排序中删除了cmp参数?

bra*_*orm 36 python sorting object cmp

来自python wiki: In Py3.0, the cmp parameter was removed entirely (as part of a larger effort to simplify and unify the language, eliminating the conflict between rich comparisons and the __cmp__ methods).

我不明白为什么在py3.0中删除cmp的原因

考虑这个例子:

>>> def numeric_compare(x, y):
        return x - y
>>> sorted([5, 2, 4, 1, 3], cmp=numeric_compare)
[1, 2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)

现在考虑这个版本(推荐并与3.0兼容):

def cmp_to_key(mycmp):
    'Convert a cmp= function into a key= function'
    class K(object):
        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
    return K

>>> sorted([5, 2, 4, 1, 3], key=cmp_to_key(reverse_numeric))
[5, 4, 3, 2, 1]
Run Code Online (Sandbox Code Playgroud)

后者非常冗长,前者只用一行就达到了同样的目的.另一方面,我正在编写我想要编写__cmp__方法的自定义类.从我在网上的小阅读,建议再写__lt__,__gt__,__eq__,__le__,__ge__,__ne__ and not __cmp__ 一次,为什么这个推荐?我不能只是定义__cmp__让生活更简单吗?

Eev*_*vee 25

对于两个物体ab,__cmp__要求之一 a < b,a == ba > b是真实的.但是,这可能并非如此:考虑套,它是非常普遍,这些都不是真实的,例如{1, 2, 3}VS {4, 5, 6}.

所以__lt__和朋友们介绍了.但是这给Python留下了两个独立的排序机制,这有点荒谬,因此在Python 3中删除的灵活性较低.

您实际上不必实现所有六种比较方法.你可以使用@total_ordering装饰器,只实现__lt____eq__.

编辑:还要注意,在排序的情况下,key函数可以比cmp以下更有效:在您给出的示例中,Python可能必须调用您的Python比较函数O(n²)次.但是key函数只需要被称为O(n)次,如果返回值是内置类型(通常是这样),则O(n²)成对比较通过C.

  • @ user1988876:丰富的比较方法解决了这个问题,因为`__lt__`和`__gt__`可以_both_返回`False`(而`__le__`和`__ge__`和`__eq__`也返回'False`,当然,只有`__ne__`返回"True").这直接表示第一组不小于,大于或等于第二组的事实. (3认同)
  • @ user1988876这是`__cmp__`问题:你必须选择三个可能的答案之一,你的第一反应是_make up_的东西,可以让你做到这一点,但他们都不是为那些两套正确的.(你不能用第一个元素来比较集合,因为它们是无序的!) (2认同)
  • 我们应该接受`cmp`函数比`key`函数更灵活,即使我们可以在99%的时间内轻松地将`cmp`转换为`key`,在某些情况下我们永远不会这样做(不是一个干净的方式),特别是当与C代码的兼容性是重要的.当C仍在使用`strcmp`时,Python会丢弃所有类型的`cmp`. (2认同)

Mar*_*ers 14

cmp被删除,因为在大多数情况下key属性为.sort()sorted()优越.它比C更能阻止C,并且引起了混乱.不必实现一个单独的__cmp__方法旁边的富比较运算符(__lt__,__gt__,等)是令人迷惑和无助.

您始终可以使用它functools.cmp_to_key()来调整现有cmp功能.

你的具体的例子可能已经实现没有一个key功能,当然,作为整数已订购; 只需添加reverse=True.

对于自定义类,使用@functools.total_ordering装饰器将一个__eq__一个比较运算符方法(例如__lt__,或__gt__等)扩展为完整的排序实现.