如果“start”参数是自定义类的实例,为什么 sum 函数会变慢?

Abd*_*P M 2 python optimization cpython python-3.x python-3.11

我在玩弄sum函数并观察到以下行为。

情况1:

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))
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我使用自定义类的实例作为函数start的参数sum。在我的系统中,对上面的代码进行基准测试大约需要几192.60747704200003秒钟的时间。

案例2:

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))
Run Code Online (Sandbox Code Playgroud)

但如果我删除自定义类实例并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)]'
Run Code Online (Sandbox Code Playgroud)

Ahm*_*AEK 5

builtin_sum_impl内部有 2 个实现,其中一个start是跳过创建 python“数字对象”的数字,而只是对 C 中的数字求和。

另一个较慢的实现当start不是数字时,这会强制__add__调用“数字对象”的方法(因为它假设您正在对一些奇怪的类求和)。

你强迫它使用较慢的一个。