我正在使用sum
函数,并观察到以下行为。
- 案例一:*
source = """
class A:
def __init__(self, a):
self.a = a
def __add__(self, other):
return self.a + other;
sum([*range(10000)], start=A(10))
"""
import timeit
print(timeit.timeit(stmt=source))
字符串
正如你所看到的,我使用了一个自定义类的示例作为sum
函数的start
参数。在我的系统中,对上面的代码进行基准测试大约需要192.60747704200003
秒。
- 案例二:*
source = """
class A:
def __init__(self, a):
self.a = a
def __add__(self, other):
return self.a + other;
sum([*range(10000)], start=10). <- Here
"""
import timeit
print(timeit.timeit(stmt=source))
型
但是如果我删除自定义类示例并直接使用int
对象,则只需要111.48285191600007
秒。我很好奇地想了解这种速度差异的原因?
我的系统信息:
>>> import platform
>>> platform.platform()
'macOS-12.5-arm64-arm-64bit'
>>> import sys
>>> sys.version
'3.11.0 (v3.11.0:deaf509e8f, Oct 24 2022, 14:43:23) [Clang 13.0.0 (clang-1300.0.29.30)]'
型
2条答案
按热度按时间vawmfj5a1#
builtin_sum_impl内部有两个实现,一个是
start
是一个数字,它跳过了创建python“数字对象”,只是在C中对数字求和。当
start
不是一个数字时,另一个较慢的实现会强制调用“number objects”的__add__
方法(因为它假设你正在对一些奇怪的类求和)。你强迫它用慢一点的
bd1hkmkf2#
也许查看字节码可以帮助理解发生了什么。
字符串
带有
start=A(10)
的版本会生成2个以上的指令:型
vs
型
start=A(10)
版本的完整字节码是here。我(有限的)理解是这两行指向
A
的初始化。请有人确认。