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.