我偶然发现了一篇博文,详细介绍了如何在Python中实现powerset函数。所以我开始尝试自己的方式,并发现Python显然不能有一组集合,因为set不可清除。这是令人厌烦的,因为powerset的定义是它是一组集合,我想使用实际的集合操作来实现它。
>>> set([ set() ])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'set'
有没有一个很好的理由Python设置不可用?
答案 0 :(得分:100)
通常,只有不可变对象在Python中可以使用。 set()
- frozenset()
的不可变变体是可以删除的。
答案 1 :(得分:26)
因为它们是可变的。
如果它们是可以清除的,那么哈希可以默默地变为“无效”,这几乎会使哈希变得毫无意义。
答案 2 :(得分:16)
来自Python文档:
<强>可哈希强>
如果对象是可清除的 有一个永远不会改变的哈希值 在它的一生中(它需要一个 哈希()方法),并且可以与其他对象进行比较(它需要一个 eq ()或 cmp ()方法)。可比较的可比较物体 必须具有相同的哈希值。可持续性使对象可用作 字典键和集合成员, 因为这些数据结构使用了 内部哈希值。
所有Python的不可变内置 对象是可清洗的,而没有可变的 容器(如列表或 字典)。对象是 用户定义的类的实例是 默认可以清洗;他们都比较 不相等,他们的哈希值是他们的 ID()。
答案 3 :(得分:6)
如果这有帮助...如果你真的需要将不可用的东西转换成可出售的等价物,你可能会做这样的事情:
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实现是here中最简单,最不严谨的示例。如果您需要更高级的HashableDict来支持酸洗和其他东西,请检查许多其他实现。在我上面的版本中,我想保留原始的dict类,从而保留OrderedDicts的顺序。我还使用来自here的AttrDict进行类似属性的访问。
我上面的例子绝不具有权威性,只是我对类似问题的解决方案,我需要将一些东西存储在一个集合中,并且需要先将它们“哈希化”。