【发布时间】:2018-02-14 13:01:56
【问题描述】:
问题
所以我编写了一个 python 函数,它通过递归生成嵌套列表的所有元素来展平列表。我想出了 2 个不同版本的生成器创建函数(不是 100% 相同)。
这里有两个版本:
def iterflatten_v1(lst):
for x in lst:
if isinstance(x, (list, tuple)):
yield from iterflatten_v1(x)
else:
yield x
def flatten_v1(lst):
return list(iterflatten_v1(lst))
def iterflatten_v2(lst):
for x in lst:
try:
yield from iterflatten_v2(x)
except TypeError:
yield x
def flatten_v2(lst):
return list(iterflatten_v2(lst))
然后我使用以下代码测试了这两个函数的速度(timing function):
import time
def timing(f, a, n):
print(f.__name__)
r = range(n)
t1 = time.clock()
for i in r:
f(a); f(a); f(a); f(a); f(a); f(a); f(a); f(a); f(a); f(a)
t2 = time.clock()
print(round(t2-t1, 3))
nested = [1, 1, 1, [1, 1, [1, 1, 1, [1, 1, 1, 1, [1, 1, 1, 1], 1, 1], 1, 1], 1], 1]
data = [nested for i in range(1000)]
timing(iterflatten_v1, data, 1000) # 0.003
timing(iterflatten_v2, data, 1000) # 0.003
timing(flatten_v1, data, 10) # 1.647
timing(flatten_v2, data, 10) # 3.005
问题
为什么iterflatten_v1 生成器的转换速度几乎是iterflatten_v2 生成器的两倍,即使生成器函数具有相同的速度?
【问题讨论】:
-
因为您在 v2 中处理了更多异常(每个叶值一个异常),所有这些都增加了开销。
-
v2 还将字符串转换为字符列表,这可能是相当意外的行为。
-
@deceze 但是 v2 的开销不会显示在它的时间上吗?还是在我遍历它们时计算生成器?
-
这让我想起了典型的“宽恕与许可”的困境。为此,你可能会觉得this post 很有趣
-
嗯,是的,除非你迭代它,否则生成器不会做任何事情。