检查dict与python中的set是否存在

检查dict与python中的set是否存在,python,performance,python-2.7,dictionary,set,Python,Performance,Python 2.7,Dictionary,Set,似乎按设置检查dict键要快一点: import random import string import timeit repeat = 3 numbers = 1000 def time(statement, _setup=None): print min( timeit.Timer(statement, setup=_setup or setup).repeat( repeat, numbers)) random.seed('slarti

似乎按设置检查dict键要快一点:

import random
import string
import timeit

repeat = 3
numbers = 1000

def time(statement, _setup=None):
    print min(
        timeit.Timer(statement, setup=_setup or setup).repeat(
            repeat, numbers))

random.seed('slartibartfast')

# Integers
length = 100000
d = {}
for _ in range(length):
    d[random.randint(0, 10000000)] = 0
s = set(d)

setup = """from __main__ import s, d, length
"""

time('for i in xrange(length): check = i in d')
time('for i in xrange(length): check = i in s')

# Strings
d = {}
for _ in range(length):
    d[''.join(random.choice(string.ascii_uppercase) for __ in range(16))] = 0
s = set(d)

test_strings= []
for _ in range(length):
    test_strings.append(random.choice(string.ascii_uppercase) for __ in range(16))

setup = """from __main__ import s, d, length, test_strings
"""

time('for i in test_strings: check = i in d')
time('for i in test_strings: check = i in s')
打印如下内容:

10.1242966769
9.73939713014
10.5156763102
10.2767765061
这是预期的还是随机的产物

想知道在高性能代码中为dict键创建集合是否值得


编辑:我的测量真的让我对底层实现感到好奇,我不是在试图节省微秒,我只是好奇——是的,如果底层实现真的倾向于集合,我可以制作一组dict键——或者不(我实际上是在修补遗留代码)。

可能取决于多种因素。在我的跑步中,字典查找速度稍快,但还不足以让我对以下内容感到兴奋:

In [1]: import numpy as np

In [2]: d = {i: True for i in np.random.random(1000)}

In [3]: s = {i for i in np.random.random(1000)}

In [4]: checks = d.keys()[:500] + list(s)[:500]

In [5]: %timeit [k in d for k in checks]
10000 loops, best of 3: 83 µs per loop

In [6]: %timeit [k in s for k in checks]
10000 loops, best of 3: 88.4 µs per loop

In [7]: d = {i: True for i in np.random.random(100000)}

In [8]: s = {i for i in np.random.random(100000)}

In [9]: checks = d.keys()[:5000] + list(s)[:5000]

In [10]: %timeit [k in d for k in checks]
1000 loops, best of 3: 865 µs per loop

In [11]: %timeit [k in s for k in checks]
1000 loops, best of 3: 929 µs per loop

老实说,这在很大程度上取决于硬件、操作系统和数据大小/限制。一般来说,在获得真正的大数据量之前,性能几乎相同。注意这里的一些运行,其中
dict
稍微好一些。在较大的数据结构大小下,内部实现细节开始主导差异,在我的机器上
set
往往表现得更好

事实上,在大多数情况下,三角洲并不重要。如果您真的想要更好的查找性能,请考虑使用<代码> Cython 或<代码> cType < /C> >,或者使用为更大的数据大小而设计的库实现。Python基类型在达到几百万个元素以上时并不意味着性能

>>> # With empty dict as setup in question
>>> time('for i in xrange(length): check = i in d')
2.83035111427
>>> time('for i in xrange(length): check = i in s')
2.87069892883
>>> d = { random.random(): None for _ in xrange(100000) }
>>> s = set(d)
>>> time('for i in xrange(length): check = i in d')
3.84766697884
>>> time('for i in xrange(length): check = i in s')
3.97955989838
>>> d = { random.randint(0, 1000000000): None for _ in xrange(100000) }
>>> s = set(d)
>>> time('for i in xrange(length): check = i in d')
3.96871709824
>>> time('for i in xrange(length): check = i in s')
3.62110710144
>>> d = { random.randint(0, 1000000000): None for _ in xrange(10000000) }
>>> s = set(d)
>>> time('for i in xrange(length): check = i in d')
10.6934559345
>>> time('for i in xrange(length): check = i in s')
5.7491569519

如果性能是如此关键,以至于毫秒的微小分数的差异会产生差异,那么Python可能是错误的语言。我希望在每100000次迭代中节省0.2秒以上的可读性。@John是的,这本身并不是一个性能问题-我开始对底层实现感到好奇-dict查找是由集合实现的吗?它们似乎不是由集合实现的,但它们使用与集合相同的基本方法。也不能保证情况会是这样,只是大O约束oh O(1)查找在合理的条件下成立。@Mr_和Mrs_这是一个有趣的问题。我的直觉是,在引擎盖下的集合是具有空值的字典,因此我会猜测查找时间实际上是相同的。它似乎比那个复杂一点。用字符串编辑