我的实际问题要大得多,但它的要点是:
def rec_func(it, newit, idx=0, seen_5=False, even_seen=0):
num = next(it, None)
if num is None:
return newit
elif num == 5: seen_5 = True
elif num&1==0: even_seen +=1
else: num*=20
newit.append(num)
print '[{}] seen_5 = {}, even_seen = {}'.format(idx, seen_5, even_seen)
return rec_func(it, newit, idx+1, seen_5, even_seen)
运行
a = []
rec_func(iter(xrange(10)), a)
print 'a =', a
但是这个设计存在一些严重的问题,递归在Python中效率不高,并且正在创建一个列表并仅仅为其结果(不是生成器)传递。试图得到这个:
a = tuple(itertools.<something>(func, iter(xrange(10)))
print a # same answer as before
我如何? - 我能想到的只有:
def func(num, state):
if num == 5: state['seen_5'] = True
elif num&1==0: state['even_seen'] +=1
else: num*=20
print '[?] seen_5 = {}, even_seen = {}'.format(state['seen_5'],
state['even_seen'])
return num
_state = {'seen_5': False, 'even_seen': 0}
print tuple(imap(partial(func, state=_state), xrange(10)))
哪个有效,但看起来有点可怕......是否有功能性解决方案?
答案 0 :(得分:1)
摆脱递归和中间列表的一种方法是使用生成器:
from __future__ import print_function
def gen(it):
idx = 0
seen_5 = False
even_seen = 0
for num in it:
if num == 5:
seen_5 = True
elif num&1==0:
even_seen +=1
else:
num *= 20
print('[{}] seen_5 = {}, even_seen = {}'.format(idx, seen_5, even_seen))
idx += 1
yield num
print('a =', list(gen(iter(range(10)))))
输出:
[0] seen_5 = False, even_seen = 1
[1] seen_5 = False, even_seen = 1
[2] seen_5 = False, even_seen = 2
[3] seen_5 = False, even_seen = 2
[4] seen_5 = False, even_seen = 3
[5] seen_5 = True, even_seen = 3
[6] seen_5 = True, even_seen = 4
[7] seen_5 = True, even_seen = 4
[8] seen_5 = True, even_seen = 5
[9] seen_5 = True, even_seen = 5
a = [0, 20, 2, 60, 4, 5, 6, 140, 8, 180]