web-dev-qa-db-fra.com

Comparez les instances d'objet pour l'égalité par leurs attributs en Python

Quel est le meilleur moyen de comparer deux instances d'un objet pour l'égalité dans Python? J'aimerais pouvoir faire quelque chose comme

Exemple:

doc1 = ErrorDocument(path='/folder',title='Page')
doc2 = ErrorDocument(path='/folder',title='Page')

if doc1 == doc2: # this should be True
    #do something

MODIFIER:

Pour clarifier davantage la question. J'aimerais comparer les valeurs d'attributs et créer une solution plus générique que 

def __eq__(self, other):
    return self.path == other.path and self.title == other.title

La méthode __eq__() devrait-elle ressembler à ceci?

def __eq__(self, other):
    # Is the other instance of the same object
    # Loop through __dict__ and compare values to attributes of other
185
Željko Živković

Comme d'habitude avec Python, c'est KISS :

class Test(object):

    def __init__(self, attr1, attr2):
        self.attr1 = attr1
        self.attr2 = attr2

    def __str__(self):
        return str(self.__dict__)

    def __eq__(self, other): 
        return self.__dict__ == other.__dict__

t1 = Test("foo", 42)
t2 = Test("foo", 42)
t3 = Test("bar", 42)

print t1, t2, t3
print t1 == t2
print t2 == t3

Il produit:

{'attr2': 42, 'attr1': 'foo'} {'attr2': 42, 'attr1': 'foo'} {'attr2': 42, 'attr1': 'bar'}
True
False

NB: sachez qu'avant Python 3.0, vous utiliseriez plutôt __cmp__ au lieu de __eq__, en procédant de la même manière.

268
e-satis

Vous remplacez les opérateurs de comparaison riches dans votre objet.

class MyClass:
 def __lt__(self, other):
      # return comparison
 def __le__(self, other):
      # return comparison
 def __eq__(self, other):
      # return comparison
 def __ne__(self, other):
      # return comparison
 def __gt__(self, other):
      # return comparison
 def __ge__(self, other):
      # return comparison

Comme ça:

    def __eq__(self, other):
        return self._id == other._id
43
Christopher

Implémentez la méthode __eq__ dans votre classe; quelque chose comme ça:

def __eq__(self, other):
    return self.path == other.path and self.title == other.title

Éditer: si vous voulez que vos objets se comparent égaux si et seulement s'ils ont des dictionnaires d'instance égaux:

def __eq__(self, other):
    return self.__dict__ == other.__dict__
5
Kiv

En résumé: 

  1. Il est conseillé d'implémenter __eq__ plutôt que __cmp__, sauf si vous exécutez python <= 2.0 (__eq__ a été ajouté dans 2.1)
  2. N'oubliez pas de mettre également en œuvre __ne__ (devrait être quelque chose comme return not self.__eq__(other) ou return not self == other sauf cas très spécial)
  3. N'oubliez pas que l'opérateur doit être implémenté dans chaque classe personnalisée que vous souhaitez comparer (voir l'exemple ci-dessous).
  4. Si vous souhaitez comparer avec un objet pouvant être Aucun, vous devez l'implémenter. L'interprète ne peut pas le deviner ... (voir exemple ci-dessous)

    class B(object):
      def __init__(self):
        self.name = "toto"
      def __eq__(self, other):
        if other is None:
          return False
        return self.name == other.name
    
    class A(object):
      def __init__(self):
        self.toto = "titi"
        self.b_inst = B()
      def __eq__(self, other):
        if other is None:
          return False
        return (self.toto, self.b_inst) == (other.toto, other.b_inst)
    
4
fievel

Lors de la comparaison d'instances d'objets, la fonction __cmp__ est appelée.

Si l'opérateur == ne fonctionne pas pour vous par défaut, vous pouvez toujours redéfinir la fonction __cmp__ pour l'objet.

Modifier:

Comme il a été souligné, la fonction __cmp__ est obsolète depuis la version 3.0 . Vous devez plutôt utiliser les méthodes “comparaison riche” .

3
Silfverstrom

Si vous souhaitez obtenir une comparaison attribut par attribut et voir si et où il échoue, vous pouvez utiliser la compréhension de la liste suivante:

[i for i,j in 
 Zip([getattr(committed_vans_events[0][0].request, attr) 
      for attr in dir(committed_vans_events[0][0].request)],
     [getattr(self.vans_states[0].onboard_passengers[0], attr) 
      for attr in dir(self.vans_states[0].onboard_passengers[0])]) 
 if not i==j]

L'avantage supplémentaire est que vous pouvez y insérer une ligne et entrer dans la fenêtre "Evaluer Expression" lors du débogage dans PyCharm.

0
DalyaG