我试图在很多教程中理解Python生成器,他们告诉我们,它们比迭代列表要快得多,所以我尝试一下,我编写了一个简单的代码。我没想到时差会这么大,有人能解释一下为什么吗?或者我做错了什么。
def f(limit):
for i in range(limit):
if(i / 7.0) % 1 == 0:
yield i
def f1(limit):
l = []
for i in range(limit):
if(i / 7.0) % 1 == 0:
l.append(i)
return l
t = timeit.Timer(stmt="f(50)", setup="from __main__ import f")
print t.timeit()
t1 = timeit.Timer(stmt="f1(50)", setup="from __main__ import f1")
print t1.timeit()
结果:t= 0.565694382945 t1 =11.9298217371
发布于 2014-07-11 19:39:37
您没有公平地比较f
和f1
。
您的第一个测试只是测量构建生成器对象所需的时间。但是,它从不对这个对象进行迭代,这意味着f
中的代码从未实际执行过(生成器只在迭代时执行它们的代码)。
然而,第二个测试测量调用f1
所需的时间。也就是说,它计算函数构建列表l
、运行for-循环到完成、多次调用list.append
、然后返回结果所需的时间。显然,这比仅仅生成生成器对象要慢得多。
为了进行公平的比较,通过将生成器f
转换为一个列表来耗尽它:
t = timeit.Timer(stmt="list(f(50))", setup="from __main__ import f")
这将导致它被完全迭代,这意味着f
中的代码现在将被执行。
发布于 2014-07-11 19:39:39
您正在计时创建生成器对象所需的时间。创建一个代码实际上并不会执行任何代码,因此您实际上是在选择一种精心设计的方法来不做任何事情。
修复之后,您会发现,当运行到完成时,生成器通常会稍微慢一些。它们的优点是,它们不需要同时将所有元素存储在内存中,并且可以中途停止。例如,当您有一个布尔值序列,并希望检查其中任何一个值是否为真时,首先使用列表计算所有值并创建它们的列表,然后再检查是否为真,而使用生成器则可以:
发布于 2014-07-11 19:47:34
https://wiki.python.org/moin/Generators在改进性能部分有一些很好的信息。虽然创建生成器可能需要一些时间,但它提供了许多优点。
下面是关于创建生成器和迭代器http://sahandsaba.com/python-iterators-generators.html的一个很好的教程。看看这个!
https://stackoverflow.com/questions/24705197
复制相似问题