我想知道是否有比下面的代码更好的标准方法或更好的方法来控制无限递归?我希望我的递归函数在最大尝试次数后放弃。下面的代码通过引入尝试方法参数并在递归调用期间递增它来实现此目的。有更好的办法吗?
def Rec(attempt=0):
if attempt==10:
return()
else:
print(attempt)
Rec(attempt=attempt+1)
Rec()
您可以创建一个装饰器,然后您可以编写适当的递归函数,具有通常的退出条件,但也可以施加递归限制:
def limit_recursion(limit):
def inner(func):
func.count = 0
def wrapper(*args, **kwargs):
func.count += 1
if func.count < limit:
result = func(*args, **kwargs)
else:
result = None
func.count -= 1
return result
return wrapper
return inner
您的代码将是(限制为 3):
@limit_recursion(limit=3)
def Rec():
print('hi')
Rec()
跑步:
>>> Rec()
hi
hi
hi
还有这种方式但不推荐用于你想做的事情 - 我发布它仅供参考,在其他情况下也很好用...
#!/usr/bin/env python
import sys
sys.setrecursionlimit(5)
def Rec(attempt=0):
print attempt
Rec(attempt=attempt+1)
try:
Rec()
except RuntimeError:
print 'maximum recursion depth exceeded'
sys.setrecursionlimit(limit)
更清楚地说,正如 python 文档中所说, sys.setrecursionlimit(limit)
的作用是:
将Python解释器堆栈的最大深度设置为limit。这 limit 防止无限递归导致 C 溢出 堆栈和 Python 崩溃。
最高可能限制取决于平台。用户可能需要 当她有一个需要深度的程序时,将限制设置得更高 递归和支持更高限制的平台。这应该是 小心操作,因为太高的限制可能会导致崩溃。
所以在我看来,除非你非常清楚自己在做什么,否则不要乱搞 Python 解释器堆栈。
你的已经很好了。这就是要走的路。它很好,因为它重量轻。您基本上需要一个
int
和一个条件分支 - 就是这样。
或者,您可以尝试保证在没有计数器的情况下打破循环(但这通常取决于具体情况)。
我在尝试防止属性更改通知中的递归时遇到了这个问题。我的解决方案是将其添加到我的通知功能中:
def myCallback():
if is_recursive_call():
return
... do stuff ...
这是
is_recursive_call
的定义:
import inspect
def is_recursive_call() -> bool:
# Get the current call stack
stack = inspect.stack()
# Get the names of the functions in the call stack
function_names = [frame.function for frame in stack]
# Check if the current function appears more than once in the call stack. Skip over element zero, which is is_recursive_call itself
current_function = function_names[1]
return function_names.count(current_function) > 1
如果您想允许递归但限制其上限,请更改为:
import inspect
def exceeds_recursion_limit(limit:int) -> bool:
# Get the current call stack
stack = inspect.stack()
# Get the names of the functions in the call stack
function_names = [frame.function for frame in stack]
# Check if the current function appears more than limit times in the call stack. Skip over element zero, which is exceeds_recursion_limit itself
current_function = function_names[1]
return function_names.count(current_function) > limit
在
exceeds_recursion_limit
中,限制为 1 可防止任何递归。
对于某些用例来说,调用堆栈操作可能太慢。
这种方法可以处理直接递归和间接递归。