Python中元组和冻结集合的区别

66

我正在使用《Python快速入门》学习Python 3,作者在书中谈到了frozenset,并指出由于set是可变的且因此不可哈希,从而不适合作为字典键,因此引入了它们的frozen版本。除了元组是有序数据结构而frozenset或更一般地说set是无序的明显区别之外,元组和frozenset之间还有其他区别吗?

4个回答

111

tuples是不可变的listsfrozensets是不可变的sets

tuples确实是有序对象的集合,但它们可以包含重复和不可哈希对象,并且具有切片功能。

frozensets没有索引,但您可以使用sets的功能- O(1)元素查找,以及诸如联合和交集等功能。它们也不能包含重复项,就像它们的可变对应项一样。


1
所以frozensets给我去重、集合操作,查找只需要常数时间,很好 :) - legends2k
@legends2k 嗯,它们仍然是集合 ;) - Volatility
是的,我看到元组和冻结集之间的所有差异实际上都是元组和集合之间的差异。 - legends2k
1
@Volatility 还有一个相似之处:tuplefrozenset 是可哈希的;而 listset 则不是。 - Elliot Cameron
1
@AndreaBergonzo 包含不可哈希对象的元组本身也是不可哈希的(例如尝试将([],)放入集合中)。但它们可以通过其他方式变为可哈希,而列表则始终不可哈希。 - Volatility
显示剩余3条评论

14

有些违反直觉 - 但这句机智的话怎么说:

sss = frozenset('abc')
sss |= set('efg')

将产生:

frozenset(['a', 'c', 'b', 'e', 'g', 'f'])
当然,这相当于 x = x | y,因此不会改变原始的 frozenset。但对于代码评审员来说,“immutable”这个术语似乎有些荒谬!

如果你输入:sss = set('abc'),它将执行相同的操作。 - Ben
@Ben,我认为你误解了意图 - frozenset是不可变的,因此在x中以不同的frozenset内容开始和结束可能会让一些代码审查者感到困惑。集合预计会发生变化,因此您需要以不同的方式阅读代码。 - F1Rumors
10
"Immutable"并不意味着你不能重复使用变量名称!如果你运行id(sss),你会发现第一个sss变量代表的对象与第二个sss变量不同。(不可变的字符串对象也是同样的道理。) - dbn

7

我想到的一个不同之处是重复问题。元组 (1, 1, 1, 1, 2, 2, 2) 将会和你期望的一模一样,但是一个frozenset将会移除所有重复的部分,只留下 frozenset([1, 2])


5

Volatility提到frozensets没有索引。我当时正在看其他功能,所以并没有立刻意识到标准的Python切片是不可能的。

a = frozenset((1, 1, 1, 1, 2, 2, 2))  # results in frozenset([1, 2])
print a[0] 

将会出现错误:

TypeError: 'frozenset' object does not support indexing

很明显它没有被索引,但是我认为值得在这里明确添加一下。


1
是的,这是因为frozenset也是set,因此不支持像set一样进行索引。 - legends2k
集合不是有序的,那么这意味着什么?如果你只想要其中的一个项目,你可以记住它们是可迭代的,然后做像print iter(a).next()这样的事情。 - F1Rumors

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接