python - 为什么 dict 与 dict.keys() 联合返回一个集合?
问题描述
正如我最初预期的那样, adict
和 a的并集set
给出TypeError
:
>>> {1:2} | {3}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for |: 'dict' and 'set'
然而,令人惊讶的是, a和的dict
并集dict.keys()
返回 a set
:
>>> {1:2} | {3:4}.keys()
{1, 3}
set.union(dict)
也有这种行为:
>>> {3}.union({1:2})
{1, 3}
但set | dict
没有,并且行为就像dict | set
:
>>> {3} | {1:2}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for |: 'set' and 'dict'
这里发生了什么?为什么在某些情况下允许使用 dict 和 set 的并集,但在其他情况下不允许,为什么在允许的情况下返回一组键?
解决方案
字典视图是“类似集合的”,但与它们不同的set
是,它们没有(类型灵活的)命名方法(如.union
您的示例中那样),它们只是具有保持类型灵活的运算符重载(因为命名方法没有存在)。
由于类型灵活,它们可以将任何可迭代对象作为其他操作数使用,并且dict
s 是它们的键(list({'a': 1, 'b': 2})
is ['a', 'b']
)的可迭代对象,因此在视图操作中会忽略这些值。并不是dict
s 在这里被特别接受,它们只是被视为任何其他可迭代对象(您可以|
使用带有dict
, list
, tuple
, range
, 生成器或类似文件的对象的字典视图,并且它们都可以工作,假设可散列的内容,并产生 aset
作为结果)。
视图更灵活并没有那么糟糕,因为它们不打算在操作后保留自己的类型,它们应该产生set
输出。set
的异位运算符更严格,因为他们不想在确定输出类型时隐式地优先考虑左侧或右侧的类型(他们不想set OP nonset
留下任何疑问结果是 typeset
还是nonset
,并且他们不想让 fornonset OP set
行为不同)。由于字典视图无论如何都不会保留类型,因此他们决定为运算符重载采用更自由的设计。view OP nonview
and的结果nonview OP view
是一致的,它总是一个set
.
支持这些特定操作的文档化原因是为了匹配以下功能collections.abc.Set
:
对于类似集合的视图,为抽象基类定义的所有操作
collections.abc.Set
都可用(例如,==
、<
或^
)。
并且由于某种原因,collections.abc.Set
不需要任何命名方法(除了isdisjoint
),只需要运算符重载。
注意:我不同意这一点(我更希望视图仅让其操作员与其他视图和set
/一起使用frozenset
,并且视图也具有命名方法以保持一致性),但是为时已晚,就是这样。
至于set
类型灵活的方法,这更像是一种有意的选择。运算符不会给人留下深刻印象,即其中一个操作数更重要,而方法必然如此(您调用它的东西显然比参数更重要)。因此,这些方法接受任意的可迭代对象(实际上,可以接受多个可迭代对象,如{1, 2, 3}.union(range(5), range(10, 15))
)并返回它们被调用的对象的类型,而操作员坚持要求类型一致以避免意外。
推荐阅读
- unreal-engine4 - 错误:无法加载游戏模块
- mysql - 如何将 MySQL MEMORY 存储引擎与 Knex 一起使用?
- javascript - 如何定义从 json 到 js 的 var?
- r - 使用 R 在组中创建具有条件的新数据框
- c# - Css 类不适用于中继器中的最后一个元素
- python - 您可以将 sha256 两次应用于单个字符串吗?
- laravel - Laravel Nova - 前端的输出形式?
- hadoop - 哪个版本的sqoop兼容hadoop 3.0
- react-native - 反应原生参考子失败
- java - 如何修复连接到 sql server 2012 错误?