2010-03-28 6 views
25

J'ai une liste d'objets que je veux transformer en ensemble. Mes objets contiennent quelques champs dont certains sont o.id et o.area. Je veux que deux objets soient égaux si ces deux champs sont identiques. c'est-à-dire: o1==o2 si et seulement si o1.area==o2.area and o1.id==o2.id.Python: comment fonctionnent les ensembles

J'ai essayé d'écraser __eq__ et __cmp__ mais j'obtiens l'erreur: TypeError: unhashable instance.

Que devrais-je remplacer?

+3

http://docs.python.org/library/stdtypes.html#set-types-set-frozenset et http://docs.python.org/glossary.html#term-hashable –

Répondre

38

Définissez la méthode __hash__ pour renvoyer un hachage significatif en fonction des champs id et area. E.g .:

def __hash__(self): 
    return hash(self.id)^hash(self.area) 
+13

Je suis un peu méfiance des mathématiques bitwise sur quelque chose comme ça. J'utiliserais quelque chose comme = return hash ((self.id, self.area)) =. –

+1

Cela risque de poser problème lors du hachage de deux composants similaires. Par exemple, hash (x)^hash (y) se comportera mal si les paires de coordonnées avec les axes permutés sont communes. Dans ce cas, il est extrêmement improbable de causer des problèmes car il est impossible de générer des ints et des chaînes avec des hachages corrélés. Cela dit, votre suggestion est toujours bonne, et j'aurais aimé y penser :-). –

9

"TypeError: instance non nettoyable." l'erreur est probablement dû à l'ancienne définition de classe i.e. .:

class A: 
    pass 

Utiliser un nouveau style à la place:

class A(object): 
    pass 

Si vous substituez __cmp__ fonction doit override __hash__ pour utiliser votre objet dans les jeux. Dans l'autre cas, hash considère toutes les instances d'objets comme inégales et la fonction __cmp__ ne sera jamais appelée.