集合操作:应该只适用于集合,但适用于 dict_keys?

问题描述 投票:0回答:3

集合操作文档说:

注意,union()、intersection()、的非运算符版本 Difference()、 symmetry_difference()、 issubset() 和 issuperset() 方法将接受任何可迭代对象作为参数。相比之下,他们的 基于运算符的对应项需要设置其参数。这 排除像

set('abc') & 'cbs'
这样容易出错的结构 更具可读性的
set('abc').intersection('cbs')

通过以下实验对此进行测试:

# Python 3.10.2 (main, Jan 15 2022, 19:56:27) [GCC 11.1.0] on linux

>>> set('ab') & set('ac')
{'a'}
# works, as expected

>>> set('ab') & 'ac'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for &: 'set' and 'str'
# doesn't work, as expected

>>> set('ab') & list('ac')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for &: 'set' and 'list'
# doesn't work, as expected

>>> set('ab') & iter('ac')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for &: 'set' and 'str_iterator'
# doesn't work, as expected

>>> set('ab') & dict(zip('ac', 'ac')).keys()
{'a'}
# works??

>>> type({}.keys())
<class 'dict_keys'>

>>> isinstance({}.keys(), (set, frozenset))
False

所以,这就是悖论:

  • set
    运算符
    &
    适用于
    dict_keys
    对象;
  • 文档说它只能与集合一起使用;
  • dict_keys
    对象不是集合。

为什么集合运算符

&
可以与 dict_keys 对象一起使用?还有其他类型可以使用吗?我如何找到这些类型的列表?

python-3.x dictionary set
3个回答
2
投票

这不是一个完整的答案,但

dict_keys
collections.abc.Set
的实例:

from collections.abc import Set
k = dict(zip('ac', 'ac')).keys()
print(isinstance(k, Set))  # -> True

1
投票

文档的这一部分指的是

set
/
frozenset
类型支持的内容。事实上,
set
不支持与
dict_keys
实例进行比较,并且它正确返回
NotImplemented
以指示不支持此操作:

>>> left = set('ab')
>>> right = dict(zip('ac', 'ac')).keys()
>>> left.__and__(right)
NotImplemented

此返回值指示 Python 应尝试与另一个操作数进行“反射操作”,以查看是否受支持。它成功了: >>> right.__rand__(left) {'a'}

如果

type(left).__and__

type(right).__rand__
都返回
NotImplemented
,那么您将看到
TypeError
异常。
因此,不存在悖论,只是数据模型中的一个微妙之处:在 

set

选择退出后,

dict_keys
类型有机会从右侧处理二元运算。
    


0
投票

集合运算符也可以在 dict_keys 和列表之间工作。 但由于某种原因,集合和列表之间没有,这似乎不一致

Python 3.10.12 (main, Sep 11 2024, 15:47:36) [GCC 11.4.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> s = {1, 2} >>> d = {2:0, 3:0} >>> l = [3, 4] >>> s - d.keys() {1} >>> d.keys() - s {3} >>> d.keys() - l {2} >>> l - d.keys() {4} >>> s -l Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for -: 'set' and 'list' >>> l - s Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for -: 'list' and 'set'

	
© www.soinside.com 2019 - 2024. All rights reserved.