如何消除Python函数中包含con的递归

2024-04-25 04:06:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个函数的形式:

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

递归部分被调用的次数太多了,我得到了一个递归错误,所以我试图用while循环来替换它,正如所解释的here,但是我无法解决如何将它与函数中的控制流语句协调起来。任何帮助都将受到感激!你知道吗


Tags: 函数inforifmydefvalsome
2条回答

可能有一个很好的确切答案,但是从递归到迭代的最通用(或者可能是快速而肮脏)的方法是manage the stack yourself。只需手动执行编程语言隐式执行的操作,并拥有自己的无限堆栈。你知道吗

在这种特殊情况下,存在tail recursion。您可以看到,my_func递归调用结果不会被调用方以任何方式使用,而是立即返回。最后发生的是,最深的递归调用的结果冒出气泡,并按原样返回。这就是为什么@outoftime的解决方案成为可能。我们只对进入递归过程感兴趣,因为递归过程的返回是微不足道的。因此,into递归过程被替换为迭代。你知道吗

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)

要使用这个decorator,只需用@TailCallerdecorator包装函数,并返回用所需参数初始化的TailCall实例。你知道吗

我想说谢谢你给@o2genum凯尔·米勒的灵感,他写了an excellent article about this problem。你知道吗

不管消除这个限制有多好,也许你必须 意识到why this feature is not officially supported。你知道吗

相关问题 更多 >