【问题标题】:Is generator faster than while loop in python?生成器比python中的while循环快吗?
【发布时间】:2016-01-17 01:30:36
【问题描述】:

问题很简单,我有以下代码在 python2 中做同样的事情:

for _ in range(n): # or xrange(),they have similar performance according to my test
    pass

i = 0
while i < n:
    i+=1
    pass

for循环比while循环快,当n = 1000000时,每个大约需要0.105544和0.2389421

  1. 从表面上看,while 循环正在执行增量边界检查,但据我所知,生成器或迭代器必须执行相同的量辛勤工作,所以如果完成的工作相同,为什么一个比另一个快?

来自python generator wiki

def generator(n):
    i = 0
    while i < n:
        yield i
        i += 1
  1. 在迭代器的情况下,通常有一个成员函数调用next,每次调用都会返回“迭代器中的下一项”,对我来说,这意味着 很多 函数调用,因此堆栈上的巨大开销(更多的汇编代码来执行推送和弹出堆栈)并且根据我对协程(生成器)的了解,它试图规避这通过创建一个新的分离堆栈(就像线程一样,它管理自己的程序计数器),虽然它不再处理大量的函数调用,但它与线程具有相同的问题,即上下文切换的开销强>.
    当 while 循环没有遇到我上面提到的任何开销时,它怎么能更慢

【问题讨论】:

    标签: python performance for-loop while-loop coroutine


    【解决方案1】:

    我希望您看到的性能差异与代码的哪些部分在 Python 中定义以及哪些在解释器中定义(在 C 中,对于 cpython)有关。例如,在for 循环案例中对next 的调用将在C 中处理,而对于range 或其他内置迭代,函数的实现也将在C 中,所以它可能很快。另一方面,while 循环的边界检查是一个 Python 表达式,需要在循环的每一轮中对其进行评估。 Python 代码几乎总是比 C 代码慢,所以在某些情况下 for 循环可能比 while 循环快并不令人震惊。

    但是请注意,这两种循环可能比您在其中执行的任何类型的有用工作都要快得多。几乎不值得将精力集中在像这样的不同类型循环之间非常小的性能差异上,而不是像算法的复杂性或数据结构的效率等更大的问题上。

    唯一的例外可能是,如果您对代码进行了大量分析,并发现特定循环是您的特定程序的最大性能瓶颈。如果是这种情况,请随心所欲地进行微优化。

    【讨论】:

    • 您很可能是正确的,而不是调用for i in range(n): 我用for i in generator(n): 替换它,其中generator() 是我在问题中定义的函数,for 循环要慢得多(0.31012297) .我对Cpython不是很熟悉,你能详细说明一下它会如何区别对待while,for range(),for generator()吗?
    • cpython 是标准的 Python 解释器(来自 python.org)。我不会太深入地弄清楚为什么一个循环比另一个循环快,因为就像我在答案中所说的那样,差异可能比您需要对代码执行的任何其他操作所花费的时间要小得多。只需使用最自然的任何一种循环,并在发现特定性能问题时进行优化。
    猜你喜欢
    • 1970-01-01
    • 2011-01-29
    • 1970-01-01
    • 2012-12-02
    • 2017-11-29
    • 1970-01-01
    • 2011-11-08
    • 2014-11-02
    • 2016-04-15
    相关资源
    最近更新 更多