【发布时间】:2013-05-19 20:29:29
【问题描述】:
在 python 中,将纯递归函数更改为递归生成器(不是普通生成器)时,性能似乎会下降。
例如,下面是两个查找列表所有组合的函数之间的性能比较:
from datetime import datetime as dt
def rec_subsets(ms, i=0, s=[]):
if i == len(ms):
# do something with s
return
rec_subsets(ms, i+1, s)
rec_subsets(ms, i+1, s + [ms[i]])
def gen_subsets(ms, i=0, s=[]):
if i == len(ms):
yield s
return
for a in gen_subsets(ms, i+1, s): yield a
for a in gen_subsets(ms, i+1, s + [ms[i]]): yield a
t1 = dt.now()
rec_subsets(range(20))
t2 = dt.now()
print t2 - t1
t1 = dt.now()
for _ in gen_subsets(range(20)): pass
t2 = dt.now()
print t2 - t1
输出如下:
0:00:01.027000 # rec_subsets
0:00:02.860000 # gen_subsets
人们自然会期望 gen_subsets 大约与 rec_subsets 一样快,但事实并非如此,它要慢得多。
这是正常的还是我错过了什么?
【问题讨论】:
-
您需要在
# do something with s处放置一些代码,然后才能进行有意义的计时。 -
没必要,gen_subsets 同样什么也不做。我在这两种情况下都做了类似的事情,以防万一(添加到一个空的全局列表)得到相同的结果。
-
但是为什么你会期望添加 yield 语句可以让代码更快呢?
-
嗯,如果这是一个有效/有根据的假设,这就是我想通过首先提出这个问题来了解的。与纯递归相比,递归生成器非常好用且用途广泛。如果他们的表现也不错,那就太好了。
-
顺便说一句,最初的问题是关于性能的,编辑不符合这个目的。
标签: python performance recursion generator