我遇到的情况是,当且仅当新值大于旧值时,必须将字典键设置为值(总是整数)。分析揭示了我目前正在做的方式是占用某个功能的整整1/3的时间。以下是我目前正在做的事情:
some_dict[k] = max(new_val, some_dict.get(k, 0))
有更快的方法吗?
答案 0 :(得分:4)
比较我能想到的三种不同方法 -
In [12]: def foo():
....: d = {1:2 , 3:4}
....: d[1] = max(3, d.get(1,0))
....:
In [13]: def foo1():
....: d = {1:2, 3:4}
....: if d.get(1,0) < 3:
....: d[1] = 3
....:
In [14]: def foo2():
....: d = {1:2, 3:4}
....: d[1] = 3 if d.get(1,0) < 3 else d.get(1)
....:
In [15]: %timeit foo()
The slowest run took 4.18 times longer than the fastest. This could mean that an intermediate result is being cached
1000000 loops, best of 3: 1 µs per loop
In [16]: %timeit foo1()
The slowest run took 11.46 times longer than the fastest. This could mean that an intermediate result is being cached
1000000 loops, best of 3: 564 ns per loop
In [17]: %timeit foo2()
The slowest run took 4.79 times longer than the fastest. This could mean that an intermediate result is being cached
1000000 loops, best of 3: 556 ns per loop
In [18]: %timeit foo()
The slowest run took 10.17 times longer than the fastest. This could mean that an intermediate result is being cached
1000000 loops, best of 3: 861 ns per loop
In [19]: %timeit foo1()
The slowest run took 5.90 times longer than the fastest. This could mean that an intermediate result is being cached
1000000 loops, best of 3: 645 ns per loop
In [20]: %timeit foo2()
The slowest run took 8.01 times longer than the fastest. This could mean that an intermediate result is being cached
1000000 loops, best of 3: 523 ns per loop
如果我们相信%timeit
的结果似乎是最快的 -
some_dict[k] = new_val if some_dict.get(k, 0) < new_val else some_dict.get(k)
这假设new_val总是大于0,因此我们在else部分不需要some_dict.get(k,0)
。尽管如此,但没有太大区别。
答案 1 :(得分:1)
嗯,显而易见的另一种方法是不总是进行赋值,而不是调用额外的函数调用:
if some_dict.get(k, 0) < new_val:
some_dict[k] = new_val
这实际上是否更快是另一个问题。
答案 2 :(得分:0)
还有另一种方法尚未提及:
get = d.get
val = get(k, 0)
d[k] = (val, new_val)[val<new_val]
此方法仅播放内存,而不使用分支。
速度有多快?嗯,它应该很快。
get = d.get
将指针保存在字典外部,以便更快地访问该方法。
您也可以使用dict.setdefault()。 这是一个有趣的小方法。
请参阅help(dict.setdefault)。