我有以下形式的功能:
def my_func(my_list):
for i, thing in enumerate(my_list):
my_val = another_func(thing)
if i == 0:
# do some stuff
else:
if my_val == something:
return my_func(my_list[:-1])
# do some other stuff
递归部分被调用得足以让我得到一个RecursionError,所以我试图用here解释的while循环替换它,但是我无法解决如何调和它函数中的控制流语句。感谢任何帮助!
答案 0 :(得分:2)
可能有一个很好的确切答案,但从递归到迭代的最通用(或者可能是快速和脏)的方法是manage the stack yourself。只需手动执行隐式编程语言,并拥有自己的无限堆栈。
在这种特殊情况下,有tail recursion。你看,调用者没有以任何方式使用my_func
递归调用结果,它会立即返回。到底发生了什么,最深的递归调用结果会冒泡并且按原样返回。这使得@outoftime的解决方案成为可能。我们只对in-recursion传递感兴趣,因为从递归返回传递是微不足道的。因此,使用迭代替换了入口递归。
答案 1 :(得分:1)
def my_func(my_list):
run = True
while run:
for i, thing in enumerate(my_list):
my_val = another_func(thing)
if i == 0:
# do some stuff
else:
if my_val == something:
my_list = my_list[:-1]
break
# do some other stuff
这是一种迭代方法。
class TailCall(object):
def __init__(self, __function__):
self.__function__ = __function__
self.args = None
self.kwargs = None
self.has_params = False
def __call__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
self.has_params = True
return self
def __handle__(self):
if not self.has_params:
raise TypeError
if type(self.__function__) is TailCaller:
return self.__function__.call(*self.args, **self.kwargs)
return self.__function__(*self.args, **self.kwargs)
class TailCaller(object):
def __init__(self, call):
self.call = call
def __call__(self, *args, **kwargs):
ret = self.call(*args, **kwargs)
while type(ret) is TailCall:
ret = ret.__handle__()
return ret
@TailCaller
def factorial(n, prev=1):
if n < 2:
return prev
return TailCall(factorial)(n-1, n * prev)
要使用此装饰器,只需使用@TailCaller
装饰器包装您的函数,并返回使用所需参数初始化的TailCall
实例。
我想感谢您对 @ o2genum 以及撰写an excellent article about this problem的 Kyle Miller 的灵感。
尽管取消这个限制有多好,但你可能必须这样做 了解why this feature is not officially supported。