Python:理解字典视图对象



我一直在尝试理解Python 3中.items().values().keys()或类似的.viewitems().viewvalues().viewkeys()返回的内置视图对象。关于这个主题还有其他的线索,但似乎没有一个(甚至是文档)描述它们是如何在内部工作的。

与Python 2中返回的list类型的副本相比,这里的主要优势似乎是效率。经常有人将窗口与字典项进行比较(如本线程中)。

但是窗口是什么?为什么它更高效?

我唯一能看到的是,视图对象似乎是像对象一样设置的,这对于成员身份测试来说通常更快。但这是唯一的因素吗?

代码示例

>>> example_dict = {'test':'test'}
>>> example_dict.items()
dict_items([('test', 'test')])
>>> type(example_dict.items())
<class 'dict_items'>

所以,我的问题是关于这个dict_items类。这在内部是如何运作的?

Dict视图存储对其父Dict的引用,并将视图上的操作转换为Dict上的相应操作。

对dict视图的迭代比构建列表并对其进行迭代更有效,因为构建列表需要时间和内存,而不必花在视图上。按照旧的方式,Python会迭代dict的底层存储以构建一个新的列表,然后您会迭代列表。对dict视图进行迭代使用一个迭代器,该迭代器直接遍历dict的底层存储,跳过不必要的列表步骤。

Dict视图还支持高效的包容测试和类集交集/差异等。操作,因为它们可以对底层dict执行直接散列查找,而不是在列表中迭代并逐元素检查相等性。

如果您想查看CPython使用的具体实现,可以查看官方存储库,但此实现可能会发生更改。它一再发生变化。

主要优势之一是视图是动态的:

>>> di={1:'one',2:'two',3:'three'}
>>> view=di.viewitems()
>>> view
dict_items([(1, 'one'), (2, 'two'), (3, 'three')])
>>> di[2]='new two'
>>> view
dict_items([(1, 'one'), (2, 'new two'), (3, 'three')])

因此,如果字典发生更改,则不需要重新生成项、键或值列表(就像使用dict.items()一样)。

将Python2dict.items()视为dict的一种复制类型——复制时的样子。

将Python 3dict.items()或等效于dict.viewitems()的Python 2视为dict现在的最新副本。(显然与.viewkey()、.viewvalues()相同。)

Python3.6文档中有一些很好的例子,说明了为什么以及何时使用它。

值视图的设置方式不同,因为dict可能有重复的值。对于具有可散列值的dict,键视图设置为类,项视图设置为类似。

注意:对于Python 3,视图将Python 2的内容替换为.keys().values().items()。有些人可能会认为dict.keys()dict.values()是dict先前状态的静态表示,这可能会让人感到惊讶。

最新更新