【问题标题】:Timeit.timeit method. Which way is correct: inner or outer?Timeit.timeit 方法。哪种方式是正确的:内部还是外部?
【发布时间】:2021-03-26 14:27:38
【问题描述】:

我想检查每个功能的速度,但遇到了问题。如您所见,下面的代码包含两个相同的函数:func & func2。但是 func 是直接在 timeit.timeit 方法中声明的。 经过测试,我得到了一个结果:Func result: 0.08, func 2 result: 0.21.。这是一个巨大的差异。

这里有一个问题:为什么相同的功能有不同的速度?从全局范围获取 func2 需要时间吗?

import timeit


def func2() -> range:
    return range(1024)


def main():
    """
    Number of seconds for each function to perform with 500k executions
    """
    func_res = round(timeit.timeit(
        'def func() -> range: return range(1024); func()',
        number=500_000
        ),
    2)
    func2_res = round(timeit.timeit(
        'func2()',
        number=500_000,
        globals=globals()
        ),
    2)
    return f'Func result: {func_res}, func 2 result: {func2_res}.'

if __name__ == '__main__':
    print(main())

附注'def func() -> range: return range(1024)' ---> 'def func() -> range: return range(1024); func()' 已被编辑。

【问题讨论】:

    标签: python timeit


    【解决方案1】:

    您正在测试的两个语句完全不同。

    第一个 (def func() -> range: return range(1024); func()) 仅测试 Python 在使用主体 return range(1024); func() 声明函数时的速度。第二个实际上调用了该函数。

    由于timeit 也可以接受可调用对象,因此您可以这样做

    timeit.timeit(
        func2,
        number=500_000,
    )
    

    无论如何。

    让我们尝试一个更好的测试平台:

    import timeit
    
    
    def func2() -> range:
        return range(1024)
    
    
    def t(name, stmt, setup="pass"):
        res = timeit.timeit(stmt, setup, number=5_000_000, globals=globals()) * 1000
        print(f"{name:>25} {int(res):5d}")
    
    
    def main():
        t("declare a func", "def func() -> range: return range(1024); func()")
        t("declare & run func", "def func() -> range: return range(1024)\nfunc()")
        t("run local func", "func()", "def func() -> range: return range(1024)")
        t("run global func2 by name", "func2()")
        t("run func2 by ref", func2)
    
    
    if __name__ == "__main__":
        main()
    

    你可以看到声明func的选项调用它也慢得多(我机器上的数字,YMMV):

               declare a func   547  # <-- doesn't call range!
           declare & run func  1282  # <-- slow...
               run local func   854  # <-- declare function once & call it
     run global func2 by name   836
             run func2 by ref   774
    

    【讨论】:

    • 谢谢!我已经更正了这个,但结果是一样的:0.1 秒 vs 0.26 秒!
    • 编辑您的问题以包含更正后的代码,我们可以看看。
    • @VladMikheenko 仍然是错误的。请参阅我的编辑。 :)
    • 为什么'declare a func'不调用范围?该字符串包含对函数 func 的调用:t("declare a func", "def func() -&gt; range: return range(1024); func()")
    • @VladMikheenko 因为 ; 被解析为分隔函数主体中的两个语句。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-11
    • 1970-01-01
    • 2015-04-24
    相关资源
    最近更新 更多