python 最大递归次数 RuntimeError: maximum recursion depth exceeded

来源:互联网 发布:瞻博网络 五百强 编辑:程序博客网 时间:2024/06/14 00:53

帮别人看代码,偶然遇到这个问题,原来python解释器有一个默认的最大递归次数是999。

举个例子:

def recursion(n):    if (n <= 1):        return    print n    recursion(n - 1)print "test 999"recursion(999)   #正常运行print "test 1000"recursion(1000)  #报错,RuntimeError: maximum recursion depth exceeded

可以在文件初始位置修改这个最大递归次数,如下:

import syssys.setrecursionlimit(10000)  # set the maximum depth as 10000

这时候递归1000次,2000次都不会报错了,但次数很大时比如5000就会报错,又查资料,结论如下:

sys.setrecursionlimit(limit)
Set the maximum depth of the Python interpreter stack to limit. This limit prevents infinite recursion from causing an overflow of the C stack and crashing Python.
The highest possible limit is platform-dependent. A user may need to set the limit higher when she has a program that requires deep recursion and a platform that supports a higher limit. This should be done with care, because a too-high limit can lead to a crash.

sys.setrecursionlimit() 只是修改解释器在解释时允许的最大递归次数,此外,限制最大递归次数的还和操作系统有关,经过测试:

windows下最大迭代次数约4400次,linux下最大迭代次数约为24900次(python 2.7 64位)

如下代码可以测试最大迭代次数:

import sysimport itertoolsclass RecursiveBlowup1:    def __init__(self):        self.__init__()def test_init():    return RecursiveBlowup1()class RecursiveBlowup2:    def __repr__(self):        return repr(self)def test_repr():    return repr(RecursiveBlowup2())class RecursiveBlowup4:    def __add__(self, x):        return x + selfdef test_add():    return RecursiveBlowup4() + RecursiveBlowup4()class RecursiveBlowup5:    def __getattr__(self, attr):        return getattr(self, attr)def test_getattr():    return RecursiveBlowup5().attrclass RecursiveBlowup6:    def __getitem__(self, item):        return self[item - 2] + self[item - 1]def test_getitem():    return RecursiveBlowup6()[5]def test_recurse():    return test_recurse()def test_cpickle(_cache={}):    try:        import cPickle    except ImportError:        print "cannot import cPickle, skipped!"        return    l = None    for n in itertools.count():        try:            l = _cache[n]            continue  # Already tried and it works, let's save some time        except KeyError:            for i in range(100):                l = [l]        cPickle.dumps(l, protocol=-1)        _cache[n] = ldef check_limit(n, test_func_name):    sys.setrecursionlimit(n)    if test_func_name.startswith("test_"):        print test_func_name[5:]    else:        print test_func_name    test_func = globals()[test_func_name]    try:        test_func()    # AttributeError can be raised because of the way e.g. PyDict_GetItem()    # silences all exceptions and returns NULL, which is usually interpreted    # as "missing attribute".    except (RuntimeError, AttributeError):        pass    else:        print "Yikes!"limit = 1000while 1:    check_limit(limit, "test_recurse")    # check_limit(limit, "test_add")    # check_limit(limit, "test_repr")    # check_limit(limit, "test_init")    # check_limit(limit, "test_getattr")    # check_limit(limit, "test_getitem")    # check_limit(limit, "test_cpickle")    print "Limit of %d is fine" % limit    limit = limit + 100
阅读全文
0 0
原创粉丝点击