Quelles méthodes doivent être remplacées/implémentées pour rendre des classes définies par l'utilisateur pouvant être triées et/ou décomposables en python?
Quels sont les pièges à surveiller?
Je tape dir({})
dans mon interprète pour obtenir une liste de méthodes sur les dict intégrés. Parmi ceux-ci, je suppose que je dois implémenter un sous-ensemble de
['__cmp__', '__eq__', '__ge__', '__gt__', '__hash__', '__le__', '__lt__', '__ne__']
Existe-t-il une différence entre les méthodes à implémenter pour Python3 et celles pour Python2?
J'ai presque posté ceci comme un commentaire aux autres réponses mais c'est vraiment une réponse en soi.
Pour que vos articles puissent être triés, ils doivent seulement implémenter __lt__
. C'est la seule méthode utilisée par le type intégré.
Les autres comparaisons ou functools.total_ordering
ne sont nécessaires que si vous voulez réellement utiliser les opérateurs de comparaison avec votre classe.
Pour rendre vos éléments passibles, vous implémentez __hash__
comme d’autres l’a noté. Vous devez également implémenter __eq__
de manière compatible - les éléments équivalents doivent avoir le même hachage.
Il n'y a pas de différence entre Python 2 et 3.
Pour la triabilité:
Vous devez définir des méthodes de comparaison. Cela rend vos articles triables. Généralement, vous ne devriez pas préférer __cmp__()
.
J'utilise habituellement functools.total_ordering decorator.
functools.total_ordering (cls) Dans une classe définissant une ou plusieurs méthodes de classement riches, ce décorateur de classe fournit le reste. Cela simplifie les efforts nécessaires pour spécifier toutes les opérations de comparaison enrichies possibles:
La classe doit définir l'un des éléments suivants:
__lt__()
,__le__()
,__gt__()
ou__ge__()
. De plus, la classe devrait fournir une méthode__eq__()
.
Vous devez faire attention à ce que vos méthodes de comparaison ne génèrent aucun effet secondaire. (changer n'importe laquelle des valeurs de l'objet)
Pour le hachage:
Vous devez implémenter la méthode __hash__()
. Je pense que le meilleur moyen est de retourner hash(repr(self))
afin que votre hash soit unique.
Il existe plusieurs façons de marquer votre objet comme pouvant être trié. Première comparaison - riche, définie par un ensemble de fonctions:
object.__lt__(self, other)
object.__le__(self, other)
object.__eq__(self, other)
object.__ne__(self, other)
object.__gt__(self, other)
object.__ge__(self, other)
De plus, il est possible de définir une seule fonction:
object.__cmp__(self, other)
Et le dernier doit être défini si vous souhaitez définir une fonction __hash__
personnalisée. Voir le doc .
La méthode Implement __lt__(self,other)
est la solution pour rendre votre classe triable.
Il peut être utilisé non seulement pour la méthode intégrée sorted(iterable)
, mais également pour la file d'attente prioritaire via le module heapq
.
De plus, je n'aime pas le design de python, tant de méthodes '__ge__', '__gt__', '__le__', '__lt__', '__ne__'
sont pas intuitives du tout!
En revanche, le Interface Comparable<T>
de Java (voir Java doc ) renvoie un entier négatif, zéro ou un entier positif, cet objet étant inférieur, égal ou supérieur à l'objet spécifié, qui est direct et convivial!