设置函数的python递归限制

设置函数的python递归限制,python,recursion,Python,Recursion,对于一个函数(实际上是一个方法)需要的递归问题,我有两个解决方案。我希望它是递归的,但我希望将递归限制设置为10,并在调用函数后重置它(或者根本不乱用递归限制)。有没有人能想出更好的方法来做这件事,或者推荐使用其中一种?我倾向于使用上下文管理器,因为它使我的代码更干净,并且没有设置回溯限制,但是可能有一些警告 import sys def func(i=1): print i if i > 10: import sys sys.traceb

对于一个函数(实际上是一个方法)需要的递归问题,我有两个解决方案。我希望它是递归的,但我希望将递归限制设置为10,并在调用函数后重置它(或者根本不乱用递归限制)。有没有人能想出更好的方法来做这件事,或者推荐使用其中一种?我倾向于使用上下文管理器,因为它使我的代码更干净,并且没有设置回溯限制,但是可能有一些警告

import sys

def func(i=1):
    print i
    if i > 10:
        import sys
        sys.tracebacklimit = 1
        raise ValueError("Recursion Limit")
    i += 1
    func(i)

class recursion_limit(object):
    def __init__(self, val):
        self.val = val
        self.old_val = sys.getrecursionlimit()
    def __enter__(self):
        sys.setrecursionlimit(self.val)
    def __exit__(self, *args):
        sys.setrecursionlimit(self.old_val)
        raise ValueError("Recursion Limit")

def func2(i=1):
    """
    Call as

    with recursion_limit(12):
        func2()
    """
    print i
    i += 1
    func2(i)

if __name__ == "__main__":
    #    print 'Running func1'
    #    func()

    with recursion_limit(12):
        func2()
不过,我确实看到上下文管理器有一些奇怪的行为。如果我把主要的

with recursion_limit(12):
    func2()
它打印1到10。如果我在解释器中也这样做,它会打印1到11。我想当我进口东西的时候,引擎盖下面一定有什么事情发生

编辑:对于后代来说,这就是我为一个知道其调用深度的函数所提出的。我怀疑我会在任何生产代码中使用它,但它完成了任务

import sys
import inspect
class KeepTrack(object):
    def __init__(self):
        self.calldepth = sys.maxint

    def func(self):
        zero = len(inspect.stack())
        if zero < self.calldepth:
            self.calldepth = zero
        i = len(inspect.stack())
        print i - self.calldepth
        if i - self.calldepth < 9:
            self.func()

keeping_track = KeepTrack()
keeping_track.func()
导入系统 进口检验 类KeepTrack(对象): 定义初始化(自): self.calldepth=sys.maxint def func(自我): 零=len(inspect.stack()) 如果零我肯定会选择第一种方法,它更简单,而且可以自我解释。毕竟递归限制是您明确的选择,那么为什么要混淆它呢?

您根本不应该更改系统递归限制。你应该编写你的函数来知道它有多深,当它变得太深时结束递归

递归限制在您的程序和解释器中的应用似乎不同,原因是它们具有不同的栈顶:解释器中调用的函数可以运行代码

虽然有点相切(我会把它放在注释中,但我认为没有空间),但应该注意,setrecursionlimit的名称有点误导性——它实际上设置了最大堆栈深度:

这就是函数根据调用位置的不同而表现不同的原因。此外,如果func2进行stdlib调用(或其他任何调用),最终调用了多个函数,从而在堆栈中添加了N个以上的函数,则会提前触发异常


此外,我也不会更改sys.tracebacklimit;这将对你计划的其他部分产生影响。使用Ned的答案。

忽略更一般的问题,看起来您可以通过查看inspect.getouterframes()的长度来获得当前帧深度。这会给你一个“零点”,你可以从中设置深度限制(免责声明:我还没有尝试过这个)


编辑:或len(inspect.stack())-我不清楚区别是什么。我很想知道这是否有效,以及它们是否不同。

为什么不在xrange(N)中使用
for uuuuu来做N次?在概念上比滥用
运行时错误
更简单,允许调用其他函数而不过早退出(或者更糟糕的是,需要调用方处理),并且作为奖励应该更有效。当你在main中这样做时,你已经在一个函数中了。当您在解释器中时,您不是。为什么您可能要这样做?您可以使用decorator检查递归限制。您可以使用decorator避免全局状态(并保持包装函数调用参数列表干净)?