据我所知,当我们只想使用一次值时,可以使用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 )
答案 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