一般来说,yield和append哪个更快?

20 投票
5 回答
14951 浏览
提问于 2025-04-16 02:49

我现在正在做一个个人学习项目,主要是读取一个XML数据库。我发现自己在写一些函数来收集数据,但不太确定用什么方法返回这些数据会比较快。

一般来说,哪种方式更快呢:

  1. yield,还是
  2. 在函数内部用好几个append(),然后再return返回一个列表?

我很想知道在什么情况下yield会比append()快,或者反过来。

5 个回答

6

有一种比TH4Ck的yielding()更快的方法,那就是列表推导。

In [245]: def list_comp():
   .....:     return [d for d in data]
   .....:

In [246]: timeit yielding()
10000 loops, best of 3: 89 us per loop

In [247]: timeit list_comp()
10000 loops, best of 3: 63.4 us per loop

当然,在不了解你代码结构的情况下去微观测试这些操作是有点傻的。它们各自在不同的情况下都有用。例如,列表推导适合用来执行一些简单的操作,这些操作可以用一句话表达。而yield的一个重要优点是可以把遍历的代码放到一个生成器方法里。到底用哪个,主要还是看你具体的使用场景。

10

我最近也在思考一个类似的问题,想找出生成一个列表(或元组)所有排列的方法,可以通过把结果加到一个列表里或者用生成器来实现。经过我的测试(以长度为9的排列为例,大约需要一秒钟左右生成),我发现:

  • 最简单的方法(排列是列表,添加到列表中,返回一个列表的列表)大约需要的时间是itertools.permutations的三倍。
  • 使用生成器(也就是用yield)可以把时间减少大约20%。
  • 使用生成器并生成元组是最快的,大约是itertools.permutations所需时间的两倍。

不过要注意,这些结果要谨慎看待!时间测量和性能分析非常有用:

if __name__ == '__main__':
    import cProfile
    cProfile.run("main()")
25

yield 的一个大优点是它是 懒惰的,而且速度通常不是使用它的 最佳 理由。但如果在你的情况下它能正常工作,那就没有理由不使用它:

# yield_vs_append.py
data = range(1000)

def yielding():
    def yielder():
        for d in data:
            yield d
    return list(yielder())

def appending():
    lst = []
    for d in data:
        lst.append(d)
    return lst

这是结果:

python2.7 -m timeit -s "from yield_vs_append import yielding,appending" "yielding()"
10000 loops, best of 3: 80.1 usec per loop

python2.7 -m timeit -s "from yield_vs_append import yielding,appending" "appending()"
10000 loops, best of 3: 130 usec per loop

至少在这个非常简单的测试中,yield 的速度比 append 更快。

撰写回答