2

如果您需要对值应用一些测试,这出现在关于迭代字典键的首选样式的挑剔讨论中。我正在比较[k for k in d if d[k] == 1]反对的表现[k for k, v in d.items() if v == 1]

看起来字典查找在 Python 3.4 中更昂贵:

$ python -m timeit -n 1000000 \
  -s 'd={k:v for v, k in enumerate("abcdefghijhklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")}' \
  '[k for k in d if d[k] == 1]'
1000000 loops, best of 3: 2.17 usec per loop

$ python -m timeit -n 1000000 \
  -s 'd={k:v for v, k in enumerate("abcdefghijhklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")}' \
  '[k for k, v in d.items() if v == 1]'
1000000 loops, best of 3: 3.13 usec per loop

$ python3.4 -m timeit -n 1000000 \
  -s 'd={k:v for v, k in enumerate("abcdefghijhklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")}' \
  '[k for k in d if d[k] == 1]'
1000000 loops, best of 3: 3.25 usec per loop

$ python3.4 -m timeit -n 1000000 \
  -s 'd={k:v for v, k in enumerate("abcdefghijhklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")}' \
  '[k for k, v in d.items() if v == 1]'
1000000 loops, best of 3: 3.05 usec per loop

与 2.7 相比,Python 3.4 中的查找成本更高吗?您能解释一下原因吗?

4

1 回答 1

5

并不是 Python 3.4 中的查找比 2.7 更昂贵1,而是dict.items()更便宜。这是因为dict.items()在语言的两个版本中是一个相当不同的野兽:

$ python2.7
Python 2.7.9 (default, Dec 11 2014, 03:19:35) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> type({}.items())
<type 'list'>
>>> 
$ python3.4
Python 3.4.2 (default, Oct  8 2014, 08:07:42) 
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> type({}.items())
<class 'dict_items'>
>>> 

在 Python 2 中,dict.items()构造并返回一个列表,而在 Python 3 中它返回一个字典视图,事实证明,将这个动态视图迭代到字典中比构造一个列表然后迭代它要快。

虽然dict.items()在 2.7 中不返回字典视图,但可以使用 获得一个dict.viewitems(),具有类似的性能优势。重复你的测试,这次viewitems()包括在内,我得到:

$ python2.7 -m timeit -n 1000000 \
  -s 'd={k:v for v, k in enumerate("abcdefghijhklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")}' \
  '[k for k in d if d[k] == 1]'
1000000 loops, best of 3: 3.38 usec per loop
$ python2.7 -m timeit -n 1000000 \
  -s 'd={k:v for v, k in enumerate("abcdefghijhklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")}' \
  '[k for k, v in d.items() if v == 1]'
1000000 loops, best of 3: 4.33 usec per loop
$ python2.7 -m timeit -n 1000000 \
  -s 'd={k:v for v, k in enumerate("abcdefghijhklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")}' \
  '[k for k, v in d.viewitems() if v == 1]'
1000000 loops, best of 3: 3.27 usec per loop

至于促使您进行调查的讨论,我想说d.items()ord.viewitems()方法更明确,因此更 Pythonic,但这实际上是一种美学选择,而不是其他任何东西。


1除了 Python 3.x 通常比 2.x 慢,但这是进步的代价......

于 2014-12-17T06:38:17.103 回答