为什么Python集不可哈希?

我偶然发现了一篇博文,详细介绍了如何在Python中实现powerset函数。 于是我开始尝试自己的做法,发现Python显然不能有一套集合,因为集合是不可散列的。 这是令人厌烦的,因为powerset的定义是它是一组集合,我想用实际集合的操作来实现它。

>>> set([ set() ]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'set' 

有没有一个很好的理由Python集不可哈希?

通常,在Python中只有不可变对象是可散列的。 set()frozenset()的不变变体是可散列的。

因为他们是可变的。

如果它们是可散列的,那么散列可能会默默地变成“无效”,这几乎使得散列毫无意义。

从Python文档:

可哈希
如果一个对象具有一个在其生命周期中从不改变的散列值(它需要一个hash ()方法),并且可以与其他对象进行比较(它需要一个eq ()或cmp ()方法),则该对象是可散列的。 比较相等的哈希对象必须具有相同的哈希值。

Hashability使对象可用作字典键和集合成员,因为这些数据结构在内部使用散列值。

所有Python的不可变内置对象都是可散列的,而没有可变容器(如列表或字典)。 对象是用户定义的类的实例默认可哈希; 他们都比较不等,他们的哈希值是他们的id()。

如果这有助于…如果你真的需要将不可破解的东西转换为可破解的等价物出于某种原因,你可能会这样做:

 from collections import Hashable, MutableSet, MutableSequence, MutableMapping def make_hashdict(value): """ Inspired by https://stackoverflow.com/questions/1151658/python-hashable-dicts - with the added bonus that it inherits from the dict type of value so OrderedDict's maintain their order and other subclasses of dict() maintain their attributes """ map_type = type(value) class HashableDict(map_type): def __init__(self, *args, **kwargs): super(HashableDict, self).__init__(*args, **kwargs) def __hash__(self): return hash(tuple(sorted(self.items()))) hashDict = HashableDict(value) return hashDict def make_hashable(value): if not isinstance(value, Hashable): if isinstance(value, MutableSet): value = frozenset(value) elif isinstance(value, MutableSequence): value = tuple(value) elif isinstance(value, MutableMapping): value = make_hashdict(value) return value my_set = set() my_set.add(make_hashable(['a', 'list'])) my_set.add(make_hashable({'a': 1, 'dict': 2})) my_set.add(make_hashable({'a', 'new', 'set'})) print my_set 

我的HashableDict实现是这里最简单,最不严谨的例子。 如果您需要更高级的支持酸洗和其他function的HashableDict,请检查其他许多实现。 在我上面的版本中,我想保留原始的dict类,从而保留OrderedDicts的顺序。 我也从这里使用AttrDict进行属性类访问。

我上面的例子不是任何权威,只是我的解决类似的问题,我需要存储在一个集合中的一些东西,需要首先“散列”他们。