比较列表和字典视图

Comparing lists with dictviews

Dictionary views "are set-like objects" 因此可用于将字典内容与其他对象进行比较。具体来说,

键视图的类集合性质允许按位比较。在 Python 3 中,我们可以使用 & 运算符找到交集。

hex_ids = {'#b0a7aa': '9976', '#595f5b': '19367', '#9a8f6a': '24095'}
hex_ids.keys()
# dict_keys(['#595f5b', '#9a8f6a', '#b0a7aa'])

{'#c7ccc0', '#9a8f6a', '#8a8e3e'} & hex_ids.keys()
# {'#9a8f6a'}

奇怪的是,比较 list 和键视图也是可能的:

['#c7ccc0', '#9a8f6a', '#8a8e3e'] & hex_ids.keys()
# {'#9a8f6a'}

listset 对象通常不能以这种方式进行比较。

['#c7ccc0', '#9a8f6a', '#8a8e3e'] & set(['#595f5b', '#9a8f6a', '#b0a7aa'])
# TypeError: unsupported operand type(s) for &: 'list' and 'set'

['#c7ccc0', '#9a8f6a', '#8a8e3e'] & {['#595f5b', '#9a8f6a', '#b0a7aa']}
# TypeError: unhashable type: 'list'

除了类似集合之外,为什么可以使用按位运算符将键视图与列表进行比较?


测试于:|Python 3.5.2|Python 3.4.4|Python 2.7.12(使用 viewkeys())|IPython 5.0 .0|

它在 dict_keys 类型上使用 __rand__ 方法(“反映和”的缩写)。注意反射函数只有在左操作数不支持对应操作且操作数类型不同的情况下才会被调用,这里就是这种情况。

>>> {}.keys().__rand__
<method-wrapper '__rand__' of dict_keys object at 0x109948f18>

例如:

>>> {0:0, 1:1}.keys().__rand__([1, 2])
{1}

出于某种原因,此方法未针对集合实现,这就是它不起作用的原因:

>>> {0, 1}.__rand__([1, 2])
NotImplemented

我不知道这个遗漏的原因,但我怀疑这可能是“没有人费心写它”,因为你可以明确地使用 set.intersection