【问题标题】:What makes an element eligible for a set membership test in Python? [duplicate]是什么让一个元素有资格在 Python 中进行集合成员资格测试? [复制]
【发布时间】:2015-11-20 19:42:16
【问题描述】:

我想了解哪些项目可以在 Python 中测试 set 成员资格。一般来说,集合成员资格测试的工作方式类似于 Python 中的list 成员资格测试。

>>> 1 in {1,2,3}
True
>>> 0 in {1,2,3}
False
>>> 

但是,集合与列表的不同之处在于它们不能包含不可散列的对象,例如嵌套集合。

列表,好的:

>>> [1,2,{1,2}]
[1, 2, {1, 2}]
>>> 

设置,因为不可散列而不起作用:

>>> {1,2,{1,2}}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'set'
>>> 

现在,即使集合不能是其他集合的成员,我们也可以在成员资格测试中使用它们。这样的检查不会导致错误。

>>> {1} in {1,2,3}
False
>>> {1,2} in {1,2,3}
False
>>> set() in {1,2,3}
False
>>> 

但是,如果我尝试在要测试的元素是 dict 的情况下进行相同的测试,我会收到一个错误,表明要测试的元素不能是不可散列的。

>>> {'a':1} in {1,2}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>> {} in {1,2}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>> 

这不可能是全部,因为 set 可以测试它是否属于另一个集合,即使它本身是不可散列的,给出结果而不是错误。

所以问题是:是什么让一个元素有资格在 Python 中进行集合成员资格测试?

【问题讨论】:

  • 呃,frozensets also 不能保存不可散列的项目 - 不同之处在于它们本身是可散列的
  • 感谢您指出这一点。它应该是指frozenset 是一个集合的可能成员,但我的文字没有反映这一点。编辑了相关评论。

标签: python collections set


【解决方案1】:

混淆是因为当你说“如果在集合中设置”时,我认为 python 将左手集合转换为冻结集合,然后对其进行测试。例如

>>> f = frozenset({1})
>>> f
frozenset([1])
>>> x = {f, 2, 3}
>>> {1} in x
True

但是,对于dict来说,没有等价于frozenset,因此它不能将dict转换为不可变对象以进行成员资格测试,因此它失败了。

我不知道这里遵循的“规则”——是否有一些通用的方法可以被覆盖以提供不可变转换,或者这种行为是否被硬编码为特定的 set在集合中。

【讨论】:

【解决方案2】:

您不能在 set 中测试不可散列元素的成员资格。示例 -

>>> [1,2] in {1,2}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> {1:2} in {1,2}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'

设置了唯一可用于包含检查的不可散列对象。正如documentation -中给出的那样

注意,__contains__()、remove() 和 discard() 方法的 elem 参数可能是一个集合。为了支持对等价的frozenset 的搜索,elem 集在搜索过程中会暂时发生变异,然后再恢复。在搜索过程中,不应该读取或改变元素集,因为它没有有意义的值。

为了支持搜索与集合具有相同元素的冻结集合,集合被临时变异为frozenset() 并进行比较。示例 -

>>> set([1,2]) in {1,2,frozenset([1,2])}
True

【讨论】:

  • 有谁知道如何从 python 函数中获取该信息?我有以下内容: >>> def f(): return set([1,2]) in {3,4} 当我做 f.func_code.co_consts 我得到 (None, 1, 2, 5, 6)但没有frozenset只有consts。我记得看过一个关于 python 优化的视频,但我不记得这个人是如何设法让 freezeset 脱离方法的。
  • 您在使用Python 2.x 吗?在 Python 3.4 中,它返回 - &gt;&gt;&gt; f.__code__.co_consts (None, 1, 2, 3, 4, frozenset({3, 4}))
  • 是的,我使用的是 2.7.10,似乎它没有将 {3, 4} 转换为冻结集......或者它只是没有显示它,因为它可能是运行时的东西跨度>
  • @Har 这是在 Python 3.2 中添加的窥视孔优化:docs.python.org/3/whatsnew/3.2.html#optimizations
猜你喜欢
  • 2011-07-11
  • 2015-09-12
  • 2012-03-02
  • 2021-10-10
  • 1970-01-01
  • 2010-11-04
  • 2016-09-19
  • 2011-08-27
  • 2017-01-29
相关资源
最近更新 更多