所以我编写了一个python函数,它通过递归地生成嵌套列表的所有元素来展平列表。我想出了两个不同版本的生成器创建功能(不是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
生成器的转换速度的两倍,即使生成器函数具有相同的速度?
答案 0 :(得分:2)
如注释中所述,在这种情况下,异常处理比测试类型实例消耗更多内存。
然而,你们两个都是正确的,时间可能因数据而异(如果数据只包含整数,你会更频繁地得到异常,而且v2甚至比它与之相比更慢V1)
请注意,如果您没有tuple
或list
的孩子,则可以使用isinstance
而不是获得50%的加速检查基类),并检查确切的类型:
def iterflatten_v1(lst):
for x in lst:
if type(x) in (list, tuple):
yield from iterflatten_v1(x)
else:
yield x
在我的机器上,我使用isinstance
版本获得1,5s,使用此版本时不到1秒。
(是的,我测试isinstance(x,collections.Sequence)
并且非常失望,因为它甚至比测试2种类型更慢)