开发者

Sets of instances

I'm trying to build a set of instances of an object, however adding instances of cer开发者_开发问答tain objects results in a TypeError: unhashable instance. Here is a minimal example:

from sets import Set
import random
from UserDict import DictMixin

class Item1(object):
    pass

class Item2(DictMixin):
    pass

item_collection = Set()

x = Item1()
y = Item2()

item_collection.add(x) # this works
print item_collection
item_collection.add(y) # this does not
print item_collection

Why does that fail and how can I get a set of instances of an object derived from DictMixin?


Your classes can, if you want, define __hash__ and comparison methods (most importantly __eq__) to be consistent with each other and "stable" -- i.e., the equality of two objects must not vary over the objects' lifetimes, and of course neither must each object's hash value vary over the object's lifetime.

The consistency requirement is: a==b must imply hash(a)==hash(b) (the reverse need not hold, and indeed rarely does).

So if you're OK with those requirements the simplest implementation would be:

class Item2(DictMixin):
    def __hash__(self): return hash(id(self))
    def __eq__(self, x): return x is self
    def __ne__(self, x): return x is not self

as it happens this would also automatically interoperate with your Item1 class, because this is the default implementation of hashing and comparison for classes that don't inherit or define other versions (as you're inheriting a different version of __eq__ from DictMixin unless you override it again).

x is self is a faster, more direct, and more concise expression of id(x) == id(self), because that is the meaning of the is operator -- identity of id (i.e., same object).

So is the fact that a==b is forced thereby to mean the same thing as a is b a problem for your application? If so, then sets are just not usable for said application and you need to think about some other, completely different data structure (one that's not based on hashing, because without the __eq__ override you can't make hashing work correctly).


In order to put things into a set, they should be hashable. Tuples for example are hashable whereas lists are not. You can make your object hashable by giving it a __hash__ method that will generate a hash key (a unique identifier for that instance of the class dependent on the data it's holding) for it.

Here is an example to trying to add a list into a set.

>>> x = [1,2,3]
>>> a=set()
>>> a.add(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

It looks like your DictMixin class is not hashable.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜