实例集

时间:2010-01-10 18:22:39

标签: python

我正在尝试构建一组对象的实例,但是添加某些对象的实例会产生TypeError: unhashable instance。这是一个最小的例子:

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

为什么会失败?如何获取从DictMixin派生的对象的一组实例?

2 个答案:

答案 0 :(得分:5)

为了将东西放入一套,它们应该是可以清洗的。例如,元组是可清除的,而列表则不是。您可以通过为其提供__hash__方法来使对象具有可缓冲性,该方法将为其生成散列键(该类的实例的唯一标识符,取决于它所持有的数据)。

以下是尝试将列表添加到集合中的示例。

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

看起来你的DictMixin课程不耐用。

答案 1 :(得分:4)

如果需要,您的类可以定义__hash__和比较方法(最重要的是__eq__)以使它们彼此一致并且“稳定” - 即,两个对象的相等性不能不同于对象的生命周期,当然,每个对象的哈希值都不会随对象的生命周期而变化。

一致性要求是:a==b 必须暗示hash(a)==hash(b)(反过来不需要保留,实际上很少有)。

因此,如果你对这些要求没问题,那么最简单的实现就是:

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

因为它会自动与您的Item1类互操作,因为这是对不继承或定义其他版本的类进行散列和比较的默认实现(因为您继承了不同的版本)来自__eq__的{​​{1}},除非您再次覆盖它。)

DictMixinx is self的更快,更直接,更简洁的表达,因为 id(x) == id(self)运算符的含义 - is(即同一个对象)。

因此,id被迫与您的应用程序的问题a==b意味着相同的事实?如果是这样,那么集合对于所述应用程序是不可用的,您需要考虑其他一些完全不同的数据结构(不是基于散列的数据结构,因为没有a is b覆盖,您无法使散列正常工作)。