Contexte :
En Python, la comparaison des objets par valeur se fait via l'opérateur '==', qui appelle en interne la méthode eq. Le comportement par défaut de cette méthode est hérité de object et compare l'identité des objets (pour la plupart des classes).
Problème :
Lorsque nous souhaitons que les instances de classes personnalisées soient comparées de manière significative (par exemple, deux objets Person différents avec le même ensemble de données considérés comme égaux), le comportement par défaut est insuffisant — il est nécessaire de définir explicitement comment la comparaison se déroule.
Solution :
Pour modifier le comportement de '==', il est nécessaire de redéfinir la méthode eq dans sa propre classe. Si la classe doit être hachable, il faudra également redéfinir hash.
Exemple de code :
class Person: def __init__(self, name, age): self.name = name self.age = age def __eq__(self, other): if not isinstance(other, Person): return NotImplemented return self.name == other.name and self.age == other.age p1 = Person("Ann", 25) p2 = Person("Ann", 25) print(p1 == p2) # True
Caractéristiques clés :
La comparaison '==' est-elle toujours symétrique pour des objets de types différents ?
Pas nécessairement — si le premier objet retourne NotImplemented, la comparaison inverse est appelée. Sinon, cela peut conduire à une asymétrie.
class A: def __eq__(self, other): return True class B: pass print(A() == B()) # True print(B() == A()) # False
Si on ne réalise pas eq, comment seront comparés les objets d'une même classe utilisateur ?
L'identité (id) sera comparée (identité en mémoire, pas les valeurs des attributs).
class Foo: def __init__(self, x): self.x = x f1 = Foo(5) f2 = Foo(5) print(f1 == f2) # False
Peut-on définir eq sans hash pour des objets qui doivent être des clés de dictionnaire ?
Non. Si eq est modifié, hash doit également être défini, sinon l'objet deviendra non hachable (TypeError lors de son utilisation comme clé).
class Foo: def __eq__(self, other): return True # hash hérité de object, mais le comportement sera imprévisible # Il vaut mieux définir explicitement __hash__
Cas négatif
Lors de la conception de la classe ValueObject dans l'équipe, on n'a pas tenu compte du fait qu'on a seulement implémenté eq, mais pas hash. En essayant d'utiliser l'objet comme clé dans un dictionnaire ou élément d'un ensemble, une exception TypeError s'est produite.
Avantages :
Implémentation rapide de la comparaison personnalisée.
Inconvénients :
Inutilisabilité des objets dans des ensembles et dictionnaires, difficulté de débogage.
Cas positif
Dans un autre projet, les développeurs ont clairement implémenté les deux méthodes — eq et hash, suivant rigoureusement la règle : si deux objets sont égaux par eq, leurs hachages coïncident.
Avantages :
Fonctionnement correct des structures de hachage, comportement cohérent, facilité de maintenance.
Inconvénients :
Perte de flexibilité : les objets égaux par valeur sont indiscernables dans les conteneurs de hachage.