我有这段代码:
s = set([5,6,7,8])
if key in s:
return True
if key not in s:
return False
在我看来,从理论上讲,它不应该在时间上有所不同,但我可能会遗漏一些内幕。
在处理时间或可读性方面,有没有理由更喜欢一个?
也许这是一个例子:
“过早优化是万恶之源”?
好的,我跑了这个测试:
import random
s = set([5,6,7,8])
for _ in range(5000000):
s.add(random.randint(-100000,100000000))
def test_in():
count = 0
for _ in range(50000):
if random.randint(-100000,100000000) in s:
count += 1
print(count)
def test_not_in():
count = 0
for _ in range(50000):
if random.randint(-100000,100000000) not in s:
count += 1
print(count)
当我计算输出时:
%timeit test_in()
10 loops, best of 3: 83.4 ms per loop
%timeit test_not_in()
10 loops, best of 3: 78.7 ms per loop
但是,这个微小的差异似乎是计算组件的一个症状。平均有47500“不是ins”,但只有2500“ins”。如果我改变两个测试通过,例如:
def test_in():
for _ in range(50000):
if random.randint(-100000,100000000) in s:
pass
结果几乎相同
%timeit test_in()
10 loops, best of 3: 77.4 ms per loop
%timeit test_not_in()
10 loops, best of 3: 78.7 ms per loop
在这种情况下,我的直觉使我失望。我原以为说it is not in the set
可能会增加一些额外的处理时间。当我进一步考虑hashmap的作用时,很明显这不是这种情况。
答案 0 :(得分:3)
你不应该看到差异。集合中的查找时间是不变的。您对该条目进行哈希处理,然后在哈希映射中查找它。所有密钥都在同一时间进行检查,并且在vs中不应该具有可比性。
答案 1 :(得分:0)
在timeit
的ipython会话中运行简单的性能测试,确认了g.d.d.c的语句。
def one(k, s):
if k in s:
return True
def two(k, s):
if k not in s:
return False
s = set(range(1, 100))
%timeit -r7 -n 10000000 one(50, s)
## 83.7 ns ± 0.874 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
%timeit -r7 -n 10000000 two(50, s)
## 86.1 ns ± 1.11 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
这样的优化不会给你带来太多好处,正如评论中指出的那样,实际上会降低你推出错误修正/改进的速度/ ......由于可读性差。对于此类低级别性能提升,我建议您调查Cython或Numba。