41

来自python 维基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]

现在考虑这个版本(推荐并兼容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]

后者非常冗长,而前者只需一行就可以达到相同的目的。另一方面,我正在编写要为其编写__cmp__方法的自定义类。从我在网上的一点阅读来看,建议写__lt__,__gt__,__eq__,__le__,__ge__,__ne__ and not __cmp__ Again,为什么要推荐这个?我不能只定义__cmp__让生活更简单吗?

4

2 回答 2

27

对于两个对象ab__cmp__要求 、和中的一个 为真。但情况可能并非如此:考虑集合,其中任何一个都不是真的很常见,例如vs 。a < ba == ba > b{1, 2, 3}{4, 5, 6}

于是__lt__和朋友介绍了。但这给 Python 留下了两个独立的排序机制,这有点荒谬,所以在 Python 3 中删除了不太灵活的排序机制。

您实际上不必实现所有六种比较方法。您可以使用@total_ordering装饰器并且只实现__lt__and __eq__

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

于 2013-11-25T20:21:12.050 回答
15

cmp被删除,因为在大多数情况下,和的key属性更优越。这是 C 语言的遗留问题,而且启动起来很混乱。必须在丰富的比较运算符(,等)旁边实现一个单独的方法是令人困惑和无益的。.sort()sorted()__cmp____lt____gt__

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

当然,您的具体示例可以在没有函数的情况下实现key,因为整数已经是可排序的;只需添加reverse=True.

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

于 2013-11-25T20:18:51.687 回答