Why aren't Python sets hashable?
我偶然发现了一篇博客文章,详细介绍了如何在python中实现powerset函数。所以我尝试了我自己的方法,发现Python显然不能有一组集合,因为集合不可散列。这是令人讨厌的,因为powerset的定义是它是一组集合,我希望使用实际的集合操作来实现它。
1 2 3 4 | >>> set([ set() ]) Traceback (most recent call last): File"<stdin>", line 1, in <module> TypeError: unhashable type: 'set' |
python集不可散列有什么好的原因吗?
通常,在Python中,只有不可变的对象才是可哈希的。
因为它们是可变的。
如果它们是可散列的,散列可能会悄悄地变为"无效",这将使散列几乎毫无意义。
从python文档中:
hashable
An object is hashable if it
has a hash value which never changes
during its lifetime (it needs a
hash() method), and can be compared to other objects (it needs an
eq() or cmp() method). Hashable objects which compare equal
must have the same hash value.Hashability makes an object usable as
a dictionary key and a set member,
because these data structures use the
hash value internally.All of Python’s immutable built-in
objects are hashable, while no mutable
containers (such as lists or
dictionaries) are. Objects which are
instances of user-defined classes are
hashable by default; they all compare
unequal, and their hash value is their
id().
号
如果这有帮助…如果出于某种原因,您确实需要将不可缓存的内容转换为可哈希等价物,那么您可能会这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 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实现是这里最简单、最不严格的例子。如果您需要一个更高级的hashabledict来支持pickle和其他功能,请检查其他许多实现。在上面的版本中,我希望保留原来的dict类,从而保留ordereddicts的顺序。我还使用这里的attrdict访问属性。
我上面的例子没有任何权威性,只是我对一个类似问题的解决方案,在这个问题中,我需要将一些东西存储在一个集合中,并且需要首先"散列"它们。