sort array python sorting object cmp

array - sorted python 3



¿Por qué se elimina el parámetro cmp de ordenar/clasificar en Python3.0? (2)

Para dos objetos a y b , __cmp__ requiere que uno de a < b , a == b , y a > b sea ​​verdadero. Pero ese podría no ser el caso: considere los conjuntos, donde es muy común que ninguno de ellos sea ​​verdadero, por ejemplo, {1, 2, 3} frente a {4, 5, 6} .

Entonces __lt__ y amigos fueron presentados. Pero eso dejó a Python con dos mecanismos de ordenamiento por separado, lo cual es un poco ridículo, por lo que el menos flexible fue eliminado en Python 3.

En realidad, no tiene que implementar los seis métodos de comparación. Puede usar @total_ordering decorator y solo implementar __lt__ y __eq__ .

editar: También tenga en cuenta que, en el caso de la ordenación, key funciones key pueden ser más eficientes que cmp : en el ejemplo que usted dio, Python puede tener que llamar a su función de comparación de Python O (n²) veces. Pero una función key solo necesita llamarse O (n) veces, y si el valor de retorno es entonces un tipo incorporado (como muy a menudo lo es), las comparaciones por pares O (n²) pasan por C.

de 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).

No entiendo el razonamiento de por qué cmp se elimina en py3.0

considera este ejemplo:

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

y ahora considere esta versión (recomendada y compatible con 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]

Este último es muy detallado y se logra el mismo objetivo en el primero con solo una línea. En otra nota, estoy escribiendo mi clase personalizada para la cual quiero escribir el método __cmp__ . desde mi pequeña lectura en la web, se recomienda escribir __lt__,__gt__,__eq__,__le__,__ge__,__ne__ and not __cmp__ De nuevo, ¿por qué esta recomendación? ¿No puedo simplemente definir __cmp__ simplificando la vida?


cmp se eliminó porque el atributo key para .sort() y sorted() es superior en la mayoría de los casos. Era una retención de C más que nada, y era confuso para arrancar. Tener que implementar un método __cmp__ separado junto a los operadores de comparación enriquecida ( __lt__ , __gt__ , etc.) fue confuso e inútil.

Siempre puede usar functools.cmp_to_key() para adaptar una función cmp existente.

Su ejemplo específico podría haberse implementado sin una función key , por supuesto, ya que los enteros ya se pueden ordenar; solo agrega reverse=True .

Para clases personalizadas, use el decorador @functools.total_ordering para expandir un __eq__ y un método de operador de comparación (por ejemplo, __gt__ o __gt__ , etc.) en una implementación de ordenamiento completo.