web-dev-qa-db-fra.com

Comment un Python set ([]) vérifie-t-il que deux objets sont égaux? Quelles méthodes un objet doit-il définir pour le personnaliser?

J'ai besoin de créer un objet ou une classe "conteneur" en Python, qui conserve un enregistrement d'autres objets que je définis également. Une exigence de ce conteneur est que si deux objets sont réputés identiques, un (l'un ou l'autre) est supprimé. Ma première pensée a été d'utiliser une set([]) comme objet contenant, pour remplir cette exigence.

Cependant, l'ensemble ne supprime pas l'une des deux instances d'objet identiques. Que dois-je définir pour en créer un?

Voici le code Python.

class Item(object):
  def __init__(self, foo, bar):
    self.foo = foo
    self.bar = bar
  def __repr__(self):
    return "Item(%s, %s)" % (self.foo, self.bar)
  def __eq__(self, other):
    if isinstance(other, Item):
      return ((self.foo == other.foo) and (self.bar == other.bar))
    else:
      return False
  def __ne__(self, other):
    return (not self.__eq__(other))

Interprète

>>> set([Item(1,2), Item(1,2)])
set([Item(1, 2), Item(1, 2)])

Il est clair que __eq__(), qui est appelée par x == y, N'est pas la méthode appelée par l'ensemble. Comment s'appelle? Quelle autre méthode dois-je définir?

Remarque: Les Item doivent rester modifiables et peuvent changer, donc je ne peux pas fournir de __hash__() méthode. Si c'est la seule façon de le faire, je vais réécrire pour utiliser des Item immuables

72
Ada

Je crains que vous n'ayez à fournir une méthode __hash__(). Mais vous pouvez le coder comme ça, cela ne dépend pas des attributs mutables de votre Item.

29
eumiro

Oui, vous avez besoin d'une méthode __hash__()- ET de l'opérateur de comparaison que vous avez déjà fourni.

class Item(object):
    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar
    def __repr__(self):
        return "Item(%s, %s)" % (self.foo, self.bar)
    def __eq__(self, other):
        if isinstance(other, Item):
            return ((self.foo == other.foo) and (self.bar == other.bar))
        else:
            return False
    def __ne__(self, other):
        return (not self.__eq__(other))
    def __hash__(self):
        return hash(self.__repr__())
67
ruena