2010-10-15 17 views
57

Necesito crear un objeto o clase 'contenedor' en Python, que guarda un registro de otros objetos que también defino. Un requisito de este contenedor es que si dos objetos se consideran idénticos, uno (cualquiera de los dos) se elimina. Lo primero que pensé fue usar un set([]) como el objeto que lo contiene, para completar este requisito.¿Cómo establece un Python ([]) si dos objetos son iguales? ¿Qué métodos necesita definir un objeto para personalizar esto?

Sin embargo, el conjunto no elimina una de las dos instancias de objeto idénticas. ¿Qué debo definir para crear uno?

Aquí está el código de 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)) 

Intérprete

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

Está claro que __eq__(), que es llamada por x == y, no es el método llamado por el conjunto. ¿Que es llamado? ¿Qué otro método debo definir?

Nota: LosItems deben permanecer mutable, y pueden cambiar, por lo que no pueden proporcionar un método__hash__(). Si esta es la única forma de hacerlo, entonces voy a reescribir para el uso de Item s inmutables.

+1

Tenía este mismo problema. Supongo que está manipulando pequeñas cantidades de datos dentro de su código. Probablemente este no sea un buen candidato para el uso de una base de datos. Recuerdo haber sido capaz de crear un conjunto y definir una función de comparación en C++ y creo que también Java, sin embargo, no parece que puedas hacer esto con objetos de diccionario en Python. Parece que alguien puede haber escrito una biblioteca "set" en Python que puede hacer esto, pero no conozco ninguno. –

Respuesta

22

Me temo que tendrá que proporcionar un método __hash__(). Pero puede codificarlo de la manera en que no depende de los atributos mutables de su Item.

+1

En el segundo párrafo aquí, señala que '__hash __()' solo se debe definir para objetos inmutables. – Ada

+1

@Nathanael: si el objeto puede tener que cambiar, puede hacer una copia inmutable del objeto, como frozenset() y set(). –

+2

@Nathhanael: ¿cómo le gustaría llamar a '__eq__'? Comparando esos (1,2) atributos? Luego, debe devolver algunos hash de (1,2) también en su método '__hash__'. – eumiro

50

Sí, necesita un __hash__() -method Y el operador de comparación que ya ha proporcionado.

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__()) 
Cuestiones relacionadas