Python 3中的生成器速度

8 投票
3 回答
881 浏览
提问于 2025-04-15 20:08

我正在查看一个关于生成器的链接,这是有人分享的。在一开始,他比较了下面的两个函数。在他的测试环境中,使用生成器的速度提高了5%。

我在使用Windows XP,Python 3.1.1,但似乎无法得到相同的结果。在用提供的日志和最多1GB的重复数据进行测试时,我一直显示“旧方法”(logs1)稍微快一些。

有没有人能帮我理解一下,为什么会有这样的不同呢?

谢谢!

def logs1():
    wwwlog = open("big-access-log")
    total = 0
    for line in wwwlog:
        bytestr = line.rsplit(None,1)[1]
        if bytestr != '-':
            total += int(bytestr)
    return total

def logs2():
    wwwlog = open("big-access-log")
    bytecolumn = (line.rsplit(None,1)[1] for line in wwwlog)
    getbytes      = (int(x) for x in bytecolumn if x != '-')
    return sum(getbytes)

*编辑,复制粘贴时格式有点乱

3 个回答

0

你等了快半个小时还没有答案。我来分享一些我理解的内容,不一定是正确的答案,但总比什么都没有好:

第一个算法使用了一个生成器。生成器的工作方式是先加载结果列表的第一页(放到内存里),然后不断加载后面的页面(也放到内存里),直到没有更多内容可以读取为止。

第二个算法使用了两个生成器,每个生成器都有一个if语句,这样每次循环就要进行两次比较,而第一个算法只需要一次比较。

另外,第二个算法在最后调用了sum函数,而第一个算法则是不断遇到相关的整数就直接加上去。

因此,对于足够大的输入,第二个算法的比较次数和额外的函数调用都比第一个算法多。这可能就是它比第一个算法花费更长时间的原因。

希望这些信息对你有帮助。

1

在你提到的David Beazley的幻灯片中,他说所有的测试都是在“OS X 10.4.11上的Python 2.5.1”下进行的,而你说你是在Windows XP上用Python 3.1进行测试的。所以,你要明白你们在比较的东西不太一样。我觉得在这两个变量中,Python的版本差别更大。

Python 3和Python 2是完全不同的东西。很多内部的东西都发生了变化(即使在Python 2的版本中也有变化)。这包括性能的优化和一些性能的下降(比如,可以看看Beazley最近关于Python 3输入输出的博客)。因此,Python性能提示页面明确指出,

你应该总是用你打算使用的Python版本和你的应用程序来测试这些提示,而不是盲目地接受某种方法比另一种更快。

我还要提到,生成器在减少内存消耗方面是很有帮助的,而不是在减少CPU消耗方面。如果你有大量数据需要从每个单独的数据中计算或提取东西,而你在之后不需要这些数据,生成器会表现得很好。想了解更多细节,可以查看生成器推导

9

说实话,这次演示中提到的速度对比,主要是想说明使用生成器并不会让程序变得特别慢。很多程序员在第一次接触生成器的时候,可能会开始担心隐藏的成本。例如,后台是不是有很多复杂的操作在进行?使用这个功能会不会让我的程序慢一倍?

通常来说,情况并不是这样的。这个例子是为了说明,使用生成器的方案在速度上基本上是一样的,有时候甚至会更快(当然,这也要看具体情况、Python的版本等等)。不过,如果你发现两种版本之间的性能差异非常大,那就值得好好研究一下了。

撰写回答