Python 实例集

Python 实例集,python,Python,我试图构建一组对象的实例,但是添加某些对象的实例会导致TypeError:unhabable 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()

我试图构建一组对象的实例,但是添加某些对象的实例会导致
TypeError:unhabable 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派生的对象的一组实例?

为了将内容放入一个集合中,它们应该是可散列的。例如,元组是可散列的,而列表则不是。您可以通过为对象提供一个
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法来使对象可散列,该方法将为对象生成散列键(该类实例的唯一标识符,取决于它所持有的数据)

下面是一个尝试将列表添加到集合中的示例

>>> x = [1,2,3]
>>> a=set()
>>> a.add(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>x=[1,2,3]
>>>a=集合()
>>>a.加入(x)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:不可损坏的类型:“列表”

看起来您的
DictMixin
类是不可散列的

为了将事物放入一个集合,它们应该是可散列的。例如,元组是可散列的,而列表则不是。您可以通过为对象提供一个
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法来使对象可散列,该方法将为对象生成散列键(该类实例的唯一标识符,取决于它所持有的数据)

下面是一个尝试将列表添加到集合中的示例

>>> x = [1,2,3]
>>> a=set()
>>> a.add(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>x=[1,2,3]
>>>a=集合()
>>>a.加入(x)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:不可损坏的类型:“列表”

看起来您的
DictMixin
类是不可散列的

如果您愿意,您的类可以定义
\uuuu hash\uuuu
和比较方法(最重要的是
\uuuuu eq\uuuu
)以彼此一致且“稳定”——即,两个对象的相等性不能随对象的生命周期而变化,当然,每个对象的哈希值也不能随对象的生命周期而变化

一致性要求是:
a==b
必须暗示
散列(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
类进行互操作,因为这是未继承或定义其他版本的类的哈希和比较的默认实现(因为您从
DictMixin
继承了不同版本的
\uuuueq\uuuu
,除非您再次重写它)

x是self
id(x)=id(self)
的更快、更直接、更简洁的表达,因为这就是
is
操作符--
id
的标识(即相同对象)的含义


因此,
a==b
这一事实是否意味着与
a是b
对您的应用程序来说是一个问题?如果是这样,那么集合就不能用于所述应用程序,您需要考虑其他完全不同的数据结构(一种不基于哈希的数据结构,因为没有
\uuuuuueq\uuuu
覆盖,您就无法使哈希正确工作)。

如果您愿意,您的类可以定义
\uuuuhash\uu
和比较方法(最重要的是
\uuuuu eq\uuuuu
)彼此一致且“稳定”——即,两个对象的相等性不得在对象的生命周期内变化,当然,每个对象的哈希值也不得在对象的生命周期内变化

一致性要求是:
a==b
必须暗示
散列(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
类进行互操作,因为这是未继承或定义其他版本的类的哈希和比较的默认实现(因为您从
DictMixin
继承了不同版本的
\uuuueq\uuuu
,除非您再次重写它)

x是self
id(x)=id(self)
的更快、更直接、更简洁的表达,因为这就是
is
操作符--
id
的标识(即相同对象)的含义


因此,
a==b
这一事实与
a是b
对您的应用程序来说是一个问题吗?如果是这样,那么集合就不能用于所述应用程序,您需要考虑其他完全不同的数据结构(一个不是基于哈希的,因为没有
\uuuuuueq\uuuuu
覆盖,就无法使哈希正确工作).

我该如何实现这一点?我不希望哈希依赖于它所持有的数据,而是希望集合的每个条目都是对特定实例的引用,而不管它所持有的数据如何,因为它可能会发生变化。类似于C术语中指向实例的指针,集合的良好查找特性是由哈希获得的这就要求对象是可散列的,因为除非你有办法将对象转换成散列,否则几乎不可能查找对象。这就是列表等可变类型无法放入集合的原因。你可以尝试使用创建对象的
id
作为散列值。我从未尝试过我不确定这是否是个好主意。你确定你想要一个集合吗?列表不行吗?我需要集合的元素是唯一的,并且需要测试成员资格,所以列表似乎不正确。使用id听起来很直观,但我不想在不了解所有后果的情况下做类似的事情。还有其他建议吗是否有更合适的数据类型?基本上,我需要一组指向具有唯一成员身份和快速查找的对象实例的指针。我该如何实现这一点?我不希望哈希依赖于它所持有的数据,而是希望集合的每个条目都是一个引用