Python 2.7 和 3.4 上的字典查找

Pau*_*ine 2 python dictionary python-2.7 python-3.x dictview

如果您需要对值应用一些测试,这是在关于迭代字典键的首选样式的挑剔讨论中提出的。我正在比较[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
Run Code Online (Sandbox Code Playgroud)

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

Zer*_*eus 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'>
>>> 
Run Code Online (Sandbox Code Playgroud)
$ 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'>
>>> 
Run Code Online (Sandbox Code Playgroud)

在 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
Run Code Online (Sandbox Code Playgroud)
$ 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
Run Code Online (Sandbox Code Playgroud)
$ 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
Run Code Online (Sandbox Code Playgroud)

至于促使您进行调查的讨论,我会说d.items()ord.viewitems()方法更明确,因此更像 pythonic,但这实际上更像是一种美学选择。


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