使用冻结集作为字典键是不是安全?

Posted

技术标签:

【中文标题】使用冻结集作为字典键是不是安全?【英文标题】:Is it safe to use frozen set as Dict key?使用冻结集作为字典键是否安全? 【发布时间】:2015-04-18 11:04:33 【问题描述】:

它显然有效,但是否存在两组相同元素碰巧在 Dict 中添加两个条目的情况?我想我早先得到了这个条件,并将我的代码从frozenset(...) 更改为tuple(sorted(frozenset(...)))。知道 Dict 和 freezeset 实施方式的人可以确认是否需要这样做吗?

【问题讨论】:

这就是它的用途。如果您有导致问题的示例,请发布。 【参考方案1】:

使用frozenset 作为dict 密钥是否安全? 是的。

根据文档,Frozenset 是可散列的,因为它是不可变的。这意味着它可以用作字典的键,因为键的先决条件是它是可散列的。

来自FrozenSet docs

frozenset 类型是不可变的和可散列的——它的内容在创建后不能更改;因此,它可以用作字典键或另一个集合的元素。

而且多余地,来自Dictionary docs:

...keys,可以是任何不可变类型


为了澄清,一个集合(根据定义),无论是否冻结,都不会保持顺序。它们在内部存储,不考虑顺序并删除了重复元素,因此以不同顺序构建的两个集合将是字典中的等效键 - 它们是相同的。

>>> frozenset([1,2,2,3,3]) == frozenset([3,2,1,1,1])
True

同样,

>>> d = 
>>> d[frozenset([1,1,2,3])] = 'hello'
>>> d[frozenset([1,2,3,3])]
'hello'
>>> d[frozenset([3,3,3,2,1,1,1])]
'hello'
>>> d[frozenset([2,1,3])]
'hello'

【讨论】:

但问题是 Frozensets 是否以不同的顺序构建,但具有相同的最终值,是否具有不同的哈希值。答案是否定的,它们没有不同的哈希值。 我认为这是可以理解的,因为根据定义,集合不保持顺序。 您回答 yes,表示您认为哈希值可能不同,因此需要 tuple(sorted(frozenset(...)))。这不是哈希性或顺序的问题,而是哈希值的问题。【参考方案2】:

是否存在两组相同元素碰巧在 Dict 中添加两个条目的情况?

没有。 frozenset hashing algorithm 不依赖于元素的顺序,只依赖于元素本身。具有相同元素的两个 FS 是相等的并且具有相同的哈希值,因此满足“dict identity”的两个条件,换句话说,它们是相同的 dict 键:

>>> a = frozenset([1,1,1,1,2,3])
>>> b = frozenset([3,3,3,3,2,1])
>>> a:1, b:2
frozenset([1, 2, 3]): 2

【讨论】:

【参考方案3】:

来自the official docs

frozenset 类型是不可变的和可散列的——它的内容在创建后不能更改; 因此它可以用作字典键或另一个集合的元素。

(重点是我的)

【讨论】:

以上是关于使用冻结集作为字典键是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 中使用 None 作为字典键是不是合理?

在啥情况下我会使用元组作为字典键?

使用有序字典作为有序集

如何在 Python 中直接获取字典键作为变量(而不是通过从值中搜索)?

在 Swift 3 中获取字典的值,哪个键不是字符串

通过将键作为列将 json 字典转换为 spark 数据帧