【问题标题】:Why is making a tuple from a generator expression slower than making one from a list comprehension?为什么从生成器表达式生成元组比从列表理解生成元组慢?
【发布时间】:2022-01-02 21:23:36
【问题描述】:

(此问题基于已删除的推文)

我同时使用 Python3.9 和 Python3.10 运行以下命令:

$ python -m timeit 'tuple([-x for x in range(1000)])'
10000 loops, best of 5: 35.7 usec per loop
$ python -m timeit 'tuple(-x for x in range(1000))'
5000 loops, best of 5: 45.7 usec per loop

令人惊讶的是,构造额外对象(列表)的版本更快。为什么会这样?如果这确实更快,为什么元组构造函数不只是在后台实例化一个列表?

注意:我还对长度为 10 和长度为 100 万的元组进行了计时,带有列表的版本总是更快。

【问题讨论】:

    标签: python-3.x performance


    【解决方案1】:

    试试这个:

    python -m timeit 'list(-x for x in range(1000))'
    

    我预计您会发现它所花费的时间与您的:

    python -m timeit 'tuple(-x for x in range(1000))'
    

    还有那个

    python -m timeit 'list([-x for x in range(1000)])'
    

    将再次恢复“丢失”的速度。

    这是因为列表与元组实际上与它无关。相反,tuple()list() 只是对 Python 的函数调用,可以调用任何东西(默认情况下,这些名称绑定到内置函数,但用户可以将它们重新绑定到任何东西)。

    [expression for vrb in ...] 是专用的语法,其含义用户代码不能更改。 Python 在编译时知道它正在构建一个列表,并生成特殊代码来利用它。该代码根本不会调用list(),而是直接自己构建列表,一次一个元素。没有实际构造生成器表达式,也没有从生成器表达式一次生成一个元素的开销。

    构建包含这些表达式的简单函数并使用dis.dis() 显示生成的字节码。代码非常不同:-)

    【讨论】:

    • 感谢您的解释!我曾认为函数调用不是重要的部分,因为差距似乎随着大小而缩放,但不需要让步是完全合理的。
    猜你喜欢
    • 2015-03-18
    • 1970-01-01
    • 1970-01-01
    • 2020-11-08
    • 1970-01-01
    • 2017-10-04
    • 2023-04-06
    • 1970-01-01
    • 2013-11-30
    相关资源
    最近更新 更多