Ошибка 'Float object is not callable' при попытке запуска кода из книги Learning Python

Ввожу код ниже полностью в интерпретаторе, цикл for в самом конце тестирует только функцию forLoop, а дальше выходит ошибка File "<stdin>", line 2, in bestoftotal TypeError: 'float object is not callable

Помогите определить, что здесь не так

    import time

    def total(reps, func, *pargs, **kargs):
        repslist = list(range(reps)) 
        start = time.perf_counter()
        for i in repslist:
        ret = func(*pargs, **kargs)
        elapsed = time.perf_counter() - start
        return (elapsed, ret)
    
    def bestof(reps, func, *pargs, **kargs):
        best = 2 ** 32 
        for i in range(reps): 
            start = time.perf_counter()
            ret = func(*pargs, **kargs)
            elapsed = time.perf_counter() - start 
            if elapsed < best: best = elapsed 
        return (best, ret)

    def bestoftotal(reps1, reps2, func, *pargs, **kargs):
        return bestof(reps1, total, reps2, func, *pargs, **kargs)

    reps = 10000
    repslist = list(range(reps))
    
    def forLoop():
        res = []
        for x in repslist:
            res.append(abs(x))
        return res

    def listComp():
        return [abs(x) for x in repslist]

    def mapCall():
        return list(map(abs, repslist))

    def genExpr():
        return list(abs(x) for x in repslist) 

    def genFunc():
        def gen():
            for x in repslist:
                yield abs(x)
        return list(gen())

    for test in (forLoop, listComp, mapCall, genExpr, genFunc):
        (bestof, (total, result)) = bestoftotal(5, 1000, test)
        print ('%-9s: %.5f => [%s...%s]' % (test.__name__, bestof, result[0], result[-1]))

Ответы (1 шт):

Автор решения: CrazyElf

У вас типичная питоновая ошибка - разные штуки в вашем коде называются одинаково.

bestof и total у вас одновременно и название функций и название переменных, которым вы присваиваете результаты работы функции bestoftotal. После такого присвоения нормальный вызов этих функций уже невозможен - вместо ссылок на функции в этих переменных лежат некие числа и Python не понимает, как можно эти числа вызвать как функции.

Починить это всё можно так, например, добавив подчёркивание к названиям переменных, совпадающих с названиями функций:

for test in (forLoop, listComp, mapCall, genExpr, genFunc):
    (bestof_, (total_, result)) = bestoftotal(5, 1000, test)
    print ('%-9s: %.5f => [%s...%s]' % (test.__name__, bestof_, result[0], result[-1]))

При этом переменная total_ у вас нигде не используется почему-то, но в целом код уже работает после такого изменения.

→ Ссылка