Python是'dict中的关键'与'key in dict.keys()'不同/更快

Yog*_*gaj 7 python performance dictionary

直觉上我认为key in dict是快于key in dict.keys().keys()创建密钥的列表.这个问题是要确认这是否属实.

只是想知道key in dict内部是否创建/使用列表来查找密钥是否存在?

另外,一种方法比另一种更快吗?

Fre*_*jer 11

简短回答:

  • 在python 2中:你的假设是正确的:dict.keys()减慢速度.
  • 在python 3中:你的假设不正确:in dict.keys()表现得像in dict

py2和py3的详细信息如下.

Python 2.7回答:

您的假设是正确的,原因如下:

  • dict.keys() 涉及额外的函数调用(堆栈开销).
  • dict.keys()返回一个列表,其中包含内存中的所有键(与惰性生成器对象相对).因此它需要分配内存.
  • key in dict可以在内部使用set对象,这是一个索引查找.key in dict.keys()是列表中的线性搜索

我创建了一个小的benckmark脚本来表明我的观点:

#! /usr/bin/python2.7

import datetime as dt
import random

dict_size = 1000000
num_iterations = 100

d = {i: i for i in xrange(dict_size)}

def f():
    k = random.randint(0,dict_size-1)
    return (k in d)

def g():
    k = random.randint(0,dict_size-1)
    return (k in d.keys())

def test(func):
    t = dt.datetime.utcnow()
    for i in xrange(num_iterations):
        func()
    print "%s --> %1.6f s" % (func, (dt.datetime.utcnow()-t).total_seconds())

test(f)
test(g)
Run Code Online (Sandbox Code Playgroud)

输出(python 2.7.6 Ubuntu 14.04):

<function f at 0x7ff2e0126d70> --> 0.000598 s
<function g at 0x7ff2e0126de8> --> 5.191553 s
Run Code Online (Sandbox Code Playgroud)

我还测试了迭代次数和交换的dict大小(只有100项dict,1M次迭代).

<function f at 0x7f94cb5e6d70> --> 3.614162 s
<function g at 0x7f94cb5e6de8> --> 7.007922 s
Run Code Online (Sandbox Code Playgroud)

这里的结果更加接近.

所以性能差异确实随着dict的大小而增长.

Python 3回答:

我改编了python 3的脚本:

  • xrange已经不见了,请range改用.(不在测试功能的性能关键内循环中,因此性能影响有限)
  • 使用大括号 print
  • 改变shabang线到 #!/usr/bin/python3

并在同一台机器上使用python 3.4.3进行测试.

  • dict_size = 1000000; num_iterations = 100

    f - > 0.000590 s g - > 0.000565 s

  • dict_size = 100; num_iterations = 1000000

    f - > 4.525487 s g - > 4.837232 s

所以在python 3中,性能差异消失了.

  • 请注意,`dict.keys()`在Python 3中返回一个类似于view对象的集合,而不是列表.而且他们也不浪费记忆. (3认同)
  • Python3.9 f 比 g 更快。在我的机器上进行 1000 万次迭代需要 12 秒到 17 秒。因此,应该不鼓励使用 .keys(),因为它的 Python 风格和性能较差。国际海事组织 (2认同)