为什么Python不支持集合嵌套?

3 投票
2 回答
2291 浏览
提问于 2025-04-18 05:32
>>> li = [2, [3, 4]]
>>> 3 in li
False

>>> {2, {3, 4}}
TypeError: unhashable type: 'set'

为什么在Python(2.x和3.x)中没有实现集合嵌套(这是数学中使用的一种概念)?

2 个回答

0

正如@Martin Pieters提到的,如果你使用frozenset对象而不是普通的集合,那是可以的,因为frozenset对象是可以被哈希的。

原因在于,Python中的普通容器(比如列表、字典、集合等)都是可变的,这意味着它们在使用过程中可以改变(比如可以往集合里添加元素)。可变的数据类型不能被哈希(因为哈希的意思就是用一个独特的数字来标识一个不可变的对象)。

frozenset对象是可以被哈希的,这意味着它们可以用在集合中,但这也意味着一旦创建了frozenset,就不能再对它进行修改(frozenset没有update()这个方法)。所以如果你想要改变一个嵌套在集合里的frozenset,你需要从这个frozenset创建一个新的集合,对这个新集合进行修改,然后把旧的frozenset移除,再把新的集合转换成frozenset并添加进去(这听起来有点复杂,如果你觉得难理解可以告诉我)。

集合只能包含可哈希对象的原因是,每个集合中的对象必须是唯一的,Python通过使用对象的哈希值来检查这一点,因为这样做既高效又安全。

18

这个功能已经实现了,但你需要使用一种叫做可哈希类型的东西。frozenset()就是这种类型。文档里也提到过这一点:

要表示集合中的集合,里面的集合必须是frozenset对象。

示例:

>>> {2, frozenset([3, 4])}
set([frozenset([3, 4]), 2])

这是因为普通的set()可变的,这和用来存储集合(和字典)的数据结构的要求不符;这些数据结构需要稳定的对象,这样在根据它们的哈希值作为表中的键时才能重新定位。

文档再次说明:

set类型是可变的——内容可以通过add()remove()等方法进行更改。由于它是可变的,所以没有哈希值,不能用作字典的键或另一个集合的元素。而frozenset类型是不可变的,并且是可哈希的——它的内容在创建后不能被更改;因此可以用作字典的键或另一个集合的元素。

撰写回答