我发现了一些奇怪的东西。
我定义了两个测试函数,如下所示:
def with_brackets(n=10000):
d = dict()
for i in range(n):
d["hello"] = i
def with_setitem(n=10000):
d = dict()
st = d.__setitem__
for i in range(n):
st("hello", i)
我们希望这两个功能的执行速度大致相同。然而:
>>> timeit(with_brackets, number=1000)
0.6558860000222921
>>> timeit(with_setitem, number=1000)
0.9857697170227766
可能有些地方我没有注意到,但看起来setitem的时间几乎是dict[key] = x的两倍长,我不是很理解为什么。难道dict[key] = x不应该调用__setitem__吗?
(使用CPython 3.9)
编辑:改用timeit而不是time
time.time
进行代码的计时,它是不可靠的。使用timeit
。 - Mark Ransomn=10000000
进行这些计算大约 25 次后,我有两个观察结果:1)我相信有时间差异,2)每次写入d.__setitem__("hello", n)
的速度甚至比您当前设置setitem
为d.__setitem__
的方法更慢。 - Kraigolastimeit
,得到了类似的结果 -with_brackets
大约比with_setitem
快两倍。而且我也认为括号会在内部转换为对__setitem__
的调用,所以我无法解释这个结果。 - Mark Ransomd["hello"]
调用PyObject_SetItem
,该函数直接调用dict_ass_sub
(通过指针mp_ass_subscript
),而st = d.__setitem__; st("hello", n)
则将该 C 调用封装在 Python 调用中(如 metatoaster 所示),这会引入更多的开销。 - YiFei