繁体   English   中英

Python生成器timeit

[英]Python generators timeit

我试图理解许多教程中的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

您没有公平地比较ff1

您的第一个测试只是测量Python 构造生成器对象所花费的时间。 但是,它永远不会迭代该对象,这意味着f内的代码永远不会实际执行(生成器仅在对其进行迭代时才执行其代码)。

但是,您的第二项测试将测量调用f1所需的时间。 意思是,它计算函数构造列表l ,运行for循环直至完成,调用list.append多次,然后返回结果。 显然,这将比仅生成生成器对象慢得多。

为了公平起见,将生成器f转换为列表以使其耗尽:

t = timeit.Timer(stmt="list(f(50))", setup="from __main__ import f")

这将导致它被完全迭代,这意味着f的代码现在将被执行。

您正在计时创建生成器对象所需的时间。 创建一个代码实际上并不会执行任何代码,因此实际上您正在计时一种精心设计的不执行任何操作的方法。

修复此问题后,您会发现生成器运行完成时通常会稍微慢一些。 它们的优势在于,它们不需要一次将所有元素存储在内存中,并且可以中途停止。 例如,当您有一系列布尔值并且要检查它们是否为真时,使用列表时,首先要计算所有值并创建它们的列表,然后再检查真值,而使用生成器时,您可以:

  • 创建第一个布尔值
  • 检查是否为真,如果是,则停止创建布尔值
  • 否则,创建第二个布尔值
  • 检查一个人是否正确,如果是,请停止创建布尔值
  • 等等。

https://wiki.python.org/moin/Generators在“提高性能”部分下有一些不错的信息。 尽管创建一个生成器可能会花费一些时间,但它具有许多优点。

  • 使用更少的内存。 通过一一创建值,整个列表就永远不会在内存中。
  • 开始的时间更少。 制作整个列表需要花费时间,而生成器可以在创建第一个值后立即使用。
  • 生成器没有设定的终点。

这是一个有关创建生成器和迭代器的好教程, 网址为http://sahandsaba.com/python-iterators-generators.html 看看这个!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM