Sweetohm

Michel Casabianca


Par défaut, Python compare les objets par leur adresse mémoire. Autrement dit, deux objets sont considérés comme égaux s’ils sont les mêmes. Souvent, on considère que deux objets sont égaux si tous leurs champs le sont.

Pour implémenter cette comparaison, on doit écrire les méthodes __eq__() et __ne__(), comme suit :

class Spam:

    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar

    def __eq__(self, other):
        if isinstance(other, self.__class__):
            return self.foo == other.foo and \
                   self.bar == other.bar
        else:
            return False

    def __ne__(self, other):
        return not self.__eq__(other)

On peut améliorer ce code en comparant les dictionnaires de ces objets :

class Spam:

    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar

    def __eq__(self, other):
        if isinstance(other, self.__class__):
            return self.__dict__ == other.__dict__
        else:
            return False

    def __ne__(self, other):
        return not self.__eq__(other)

Mais on peut faire encore mieux en écrivant un Mixin :

class EqualMixin:

    def __eq__(self, other):
        if isinstance(other, self.__class__):
            return self.__dict__ == other.__dict__
        else:
            return False

    def __ne__(self, other):
        return not self.__eq__(other)

Un mixin est une classe qui implémente une fonctionnalité transverse (ici la comparaison d’instances). On en héritera pour ajouter cette fonctionnalité à une autre classe. Dans la mesure où l’héritage multiple est possible en Python, on peut ainsi ajouter des fonctionnalités dans une classe à l’aide de mixins.

class Spam(EqualMixin):

    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar

Cette classe permet ainsi de simplifier les tests unitaires : on pourra tester l’égalité d’objets avec un simple assertEqual(), sans avoir à comparer tous les champs individuellement.

Enjoy!