Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
对于Python字典来说,iterkeys比viewkeys有什么优势吗?_Python_Python 2.7 - Fatal编程技术网

对于Python字典来说,iterkeys比viewkeys有什么优势吗?

对于Python字典来说,iterkeys比viewkeys有什么优势吗?,python,python-2.7,Python,Python 2.7,在Python2.7中,字典既有iterkeys方法,也有viewkeys方法(以及类似的值和项对),提供了两种不同的方法来惰性地迭代字典的键。viewkeys方法提供了iterkeys的主要功能,其中iter(d.viewkeys())有效地等同于d.iterkeys()。此外,返回的对象viewkeys具有方便的set-like功能。因此,有充分的理由支持viewkeys而不是iterkeys 另一个方向呢?除了与早期版本的Python兼容外,iterkeys是否有比viewkeys更好的方

在Python2.7中,字典既有
iterkeys
方法,也有
viewkeys
方法(以及类似的值和项对),提供了两种不同的方法来惰性地迭代字典的键。
viewkeys
方法提供了
iterkeys
的主要功能,其中
iter(d.viewkeys())
有效地等同于
d.iterkeys()
。此外,返回的对象
viewkeys
具有方便的set-like功能。因此,有充分的理由支持
viewkeys
而不是
iterkeys


另一个方向呢?除了与早期版本的Python兼容外,
iterkeys
是否有比
viewkeys
更好的方式?总是使用
viewkeys
会丢失任何东西吗

字典视图会随着字典的更新而更新,而迭代器不一定会这样做

这意味着,如果使用视图,更改词典,然后再次使用视图,则视图将已更改以反映词典的新状态

它们提供字典条目的动态视图,这意味着当字典更改时,视图会反映这些更改。

例如:

>>> test = {1: 2, 3: 4}
>>> a = test.iterkeys()
>>> b = test.viewkeys()
>>> del test[1]
>>> test[5] = 6
>>> list(a)
[3, 5]
>>> b
dict_keys([3, 5])
更改大小时,将引发异常:

>>> test = {1: 2, 3: 4}
>>> a = test.iterkeys()
>>> b = test.viewkeys()
>>> test[5] = 6
>>> list(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: dictionary changed size during iteration
>>> b
dict_keys([1, 3, 5])

不,使用
iterkeys
比使用
viewkeys
没有任何好处,就像使用
键对这两种键都没有好处一样<代码>iterkeys
仅用于背面兼容性。实际上,在Python3中,
viewkeys
是唯一仍然存在的行为,它被重命名为
keys
viewkeys
方法实际上是Python3行为的一个后端口。
viewkeys()
viewvalues()
viewitems()
方法返回字典中当前元素的视图,这意味着如果字典更改,视图也会更改;意见是一致的。在一般情况下,键视图设置为,而项视图仅在值可散列时设置为

在什么情况下,最好使用标准方法
keys()
values()
items()
?您提到了一个非常重要的问题:向后兼容性。此外,当您需要一个包含所有键、值或项的简单列表(不是像迭代器那样的集合)时,当您需要修改返回的列表而不修改原始字典时,以及当您需要一个字典键、值或项的快照时,与字典上的任何后续修改无关


那么
iterkeys()
itervalues()
iteritems()
呢?当您需要字典内容的一次性、恒定空间、惰性迭代器快照时,它们是一个合适的选择,它将告诉您字典在迭代时是否被修改(通过
运行时错误
),而且它们对于向后兼容性非常重要。

正如您所观察到的,从功能角度来看,视图更好。就兼容性而言,它们更糟糕

一些性能指标取自64位Ubuntu机器上的Python 2.7.2:

>>> from timeit import timeit
处理空字典:

>>> emptydict = {}
>>> timeit(lambda: emptydict.viewkeys())
0.24384498596191406
>>> timeit(lambda: list(emptydict.viewkeys()))
0.4636681079864502
>>> timeit(lambda: emptydict.iterkeys())
0.23939013481140137
>>> timeit(lambda: list(emptydict.iterkeys()))
1.0098130702972412
>>> fulldict = {i: i for i in xrange(1000)}
>>> timeit(lambda: fulldict.viewkeys())
0.24295306205749512
>>> timeit(lambda: list(fulldict.viewkeys()))
13.447425842285156
>>> timeit(lambda: fulldict.iterkeys())
0.23759889602661133
>>> timeit(lambda: list(fulldict.iterkeys()))
15.45390510559082
构造视图稍微贵一些,但是使用视图要比迭代器快很多(快一倍多一点)

处理千元素词典:

>>> emptydict = {}
>>> timeit(lambda: emptydict.viewkeys())
0.24384498596191406
>>> timeit(lambda: list(emptydict.viewkeys()))
0.4636681079864502
>>> timeit(lambda: emptydict.iterkeys())
0.23939013481140137
>>> timeit(lambda: list(emptydict.iterkeys()))
1.0098130702972412
>>> fulldict = {i: i for i in xrange(1000)}
>>> timeit(lambda: fulldict.viewkeys())
0.24295306205749512
>>> timeit(lambda: list(fulldict.viewkeys()))
13.447425842285156
>>> timeit(lambda: fulldict.iterkeys())
0.23759889602661133
>>> timeit(lambda: list(fulldict.iterkeys()))
15.45390510559082
结果相同,但不太显著;构建视图的成本稍微高一点,但使用视图的速度肯定更快(快15%)

为了与
list(dict.viewkeys())
list(dict.iterkeys())
进行公平的比较,
dict.keys()
分别是:

>>> timeit(lambda: emptydict.keys())
0.2385849952697754
>>> timeit(lambda: fulldict.keys())
7.842105150222778
总结:这是一种权衡;与更好的兼容性和肌肉记忆使用相比,更好的功能(您很少会使用)和性能(如果您关心这些性能问题,您可能已经处于需要使用numpy/scipy的区域,这很少会让您担心)


就个人而言,除非已经依赖于2.7-only功能,或者除非我完全控制运行时环境,否则我将避免在Python2代码中使用字典视图。即使在这种情况下,我的手指仍然想输入
iter
,而不是
view
,所以我让他们

“除了与早期版本的Python兼容之外”——事实是,这是一个你很难称之为无关的东西。否则,每个人都会使用Python3.2already@vartec这不是无关紧要的,但很明显。但是,除此之外,
iterkeys()
viewkeys()
@vartec相比没有优势,谢天谢地,他没有说那是无关紧要的,那么!这完全正确,但实际上并没有解决这个问题-OP知道
viewkeys
的作用,并且特别询问假装
iterkeys
不存在是否有任何缺点。@lvc解释了这些差异,这可以被认为是
iterkeys()
的积极作用-例如,您不希望它被更新,使用
iterkeys()
可能更合适(尽管可以使用
viewkeys()
创建相同的功能)。我并不是说这是一个强有力的理由,但这几乎是唯一的理由。@larsmans one可以说,这比在你不希望更新的版本上默默工作要好,但我同意这是一个延伸。是的,简单的回答是没有理由使用
iterkeys()
,这就是为什么它在Python3中消失了。然而,我想我应该解释一下它们之间的区别,希望它能把区别弄清楚。重要的是要意识到迭代器不会因为词汇的任何更改而引发
运行时错误