生成器比列表理解慢

时间:2018-11-16 11:18:38

标签: python performance

据我所知,当我们只想使用一次值时,可以使用generator。使用下面的2个示例,我的逻辑是第二个示例应该更快,因为第一个示例首先创建一个列表,然后遍历这些值..而第二个示例仅处理生成器中的值。但是,当我计算时间时,列表理解总是比生成器快。为什么会这样?

第一:

x = []
a = time.perf_counter()
for j in [i**2 for i in range(20000)]:
    x.append(j)
print( time.perf_counter() - a )

第二:

x = []
a = time.perf_counter()
for j in (i**2 for i in range(20000)):
    x.append(j)
print( time.perf_counter() - a )

1 个答案:

答案 0 :(得分:4)

是的,生成器和genexprs通常比列表理解要慢(嘿),但是另一方面,它们的计算比较懒惰,您也不必为完全预先计算的列表支付存储成本。我认为速度差异是由于调用帧开销((隐式或显式)yield抛出值)引起的。

使用您的代码,但使用timeit进行测量,并使用生成器函数使用第三个版本:

import timeit

def f1():
    x = []
    for j in [i**2 for i in range(20000)]:
        x.append(j)
    return x

def f2():
    x = []
    for j in (i**2 for i in range(20000)):
        x.append(j)
    return x


def f3():
    def gen():
        for i in range(20000):
            yield i ** 2
    x = []
    for j in gen():
        x.append(j)
    return x


print(timeit.timeit(f1, number=100))
print(timeit.timeit(f2, number=100))
print(timeit.timeit(f3, number=100))

结果(Python 3.7.0)似乎表明genexprs与生成器函数完全一样快,比列表理解慢大约4-5%。

f1 = 2.882695159
f2 = 3.0303254170000002
f3 = 3.002670741