Подтвердить что ты не робот

Почему параметр cmp удален из sort/sorted в Python3.0?

из 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).

Я не понимаю причины, почему cmp удаляется в py3.0

рассмотрим этот пример:

>>> 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__ Опять же, почему эта рекомендация? могу ли я просто определить __cmp__ сделать жизнь проще?

4b9b3361

Ответ 1

Для двух объектов a и b, __cmp__ требуется, чтобы один из a < b, a == b и a > b был истинным. Но это может быть не так: рассмотрите множества, где очень распространено, что ни одно из них не является истинным, например. {1, 2, 3} vs {4, 5, 6}.

Итак, __lt__ и друзья были представлены. Но это оставило Python с двумя отдельными механизмами упорядочения, что довольно смешно, поэтому менее гибкий был удален в Python 3.

На самом деле вам не нужно реализовывать все шесть методов сравнения. Вы можете использовать @total_ordering декоратор и использовать только __lt__ и __eq__.

edit: Также обратите внимание, что в случае сортировки функции key могут быть более эффективными, чем cmp: в примере, который вы дали, Python, возможно, придется вызывать функцию сравнения Python O (n²) раз. Но функция key должна быть вызвана только O (n) раз, а если возвращаемое значение является встроенным (как это часто бывает), то парные сравнения O (n²) проходят через C.

Ответ 2

cmp был удален, потому что атрибут key для .sort() и sorted() превосходит в большинстве случаев. Это было больше, чем когда-либо, и сбивало с толку ботинок. Необходимость реализовать отдельный метод __cmp__ рядом с богатыми операторами сравнения (__lt__, __gt__ и т.д.) Была путаной и бесполезной.

Вы можете всегда использовать functools.cmp_to_key() для адаптации существующей функции cmp.

Ваш конкретный пример мог быть реализован без функции key, конечно, поскольку целые числа уже заказываются; просто добавьте reverse=True.

Для пользовательских классов используйте @functools.total_ordering decorator, чтобы развернуть __eq__ и один метод оператора сравнения (например, __lt__, или __gt__ и т.д.) в реализацию полного упорядочения.