【问题标题】:Why are generators faster?为什么生成器更快?
【发布时间】:2015-10-24 08:18:41
【问题描述】:

我知道生成器比迭代器快。我也明白生成器可以使用for 循环语法来实现。例如:

    import time 


startT = time.time()


def myGen(n):
    for i in range(n):
        yield x         


def myIter(n):
    for i in range(n):
        pass

def main():
    n=100
    startT=time.time()
    myIter(n)
    print 'myIter took ', time.time() - startT

    startT=time.time()
    myGen(n)
    print 'myGen(n) took ', time.time() - startT

这只是结果的一个例子:

myIter took 0.09234782
myGen(n) took 0.017847266

由于它使用for 循环语法,所以我不明白它比迭代器快得多。此生成器使用迭代器,因为“for”循环是使用迭代器实现的。如果您对这些进行计时,则生成器始终会更快。当生成器使用迭代器时,为什么会这样?

谢谢。

【问题讨论】:

  • “我知道生成器比迭代器快。” - 他们不是。为什么你认为他们是?生成器是一种迭代器。
  • 生成器并不比迭代器快。生成器迭代器。通常生成器函数实际上更慢,但内存效率更高。
  • 不清楚你认为这比什么代码更快。你能把它包括在你的问题中吗?
  • 还有printing标准输出变量也会减慢应用程序的速度。
  • 首先,您只进行了一次测试,而不是数千次。其次,time.time() 不是一个准确的计时器。第三,生成器只创建循环并进行一次迭代,而另一个函数创建循环然后遍历整个循环

标签: python iterator generator


【解决方案1】:

在您的代码中,myIter(n) 确实有效——它循环了 100 次。

另一方面,myGen(n) 只是构建生成器——仅此而已。它不算到 100。你所做的只是计算构建对象所需的时间,而你正在以一种不可靠的方式计算它。如果我们使用timeit(这里使用 IPython 让事情变得更简单):

>>> %timeit myIter(100)
1000000 loops, best of 3: 1 µs per loop
>>> %timeit myGen(100)
10000000 loops, best of 3: 163 ns per loop
>>> %timeit myGen(10**1000)
10000000 loops, best of 3: 163 ns per loop

我们看到myGen(n) 时间独立于n,因为它没有做任何事情。事实上,我们可以看到您的代码从未以其他方式执行:

>>> list(myGen(100))
Traceback (most recent call last):
  File "<ipython-input-11-dd43d937402a>", line 1, in <module>
    list(myGen(100))
  File "<ipython-input-1-ba968e48e9fd>", line 3, in myGen
    yield x
NameError: name 'x' is not defined

如果我们修正这个错字,然后尝试一种快速的方式来消耗生成器,我们会得到类似的东西

>>> %timeit myIter(100)
1000000 loops, best of 3: 1 µs per loop
>>> %timeit consume(myGen(100), 100)
100000 loops, best of 3: 3.44 µs per loop

而且生成器版本更慢,这通常是这种情况。

【讨论】:

    猜你喜欢
    • 2016-12-02
    • 2020-07-17
    • 2019-06-18
    • 2020-11-08
    • 2016-11-10
    • 2012-07-21
    • 1970-01-01
    • 2022-01-20
    • 2018-02-15
    相关资源
    最近更新 更多