繁体   English   中英

为什么这个Python脚本会创建一个无限循环? (递归)

[英]Why does this Python script create an infinite loop? (recursion)

为什么/如何创建一个看似无限的循环? 错误地,我认为这会导致某种形式的堆栈溢出类型错误。

i = 0

def foo () :
    global i

    i += 1
    try :
        foo()
    except RuntimeError :
        # This call recursively goes off toward infinity, apparently.
        foo()

foo()

print i

如果超出递归限制,将引发RuntimeError异常。

由于您正在捕获此异常,因此您的计算机将继续运行,但您只需添加一个全局int值,该值不会占用太多内存。

您可以使用sys.setrecursionlimit()设置递归限制。 可以使用sys.getrecursionlimit()找到当前限制。

>>> import sys
>>> sys.setrecursionlimit(100)
>>>
>>> def foo(i):
...     i += 1
...     foo(i)
...
>>> foo(1)
Traceback (most recent call last):
  ...
  File "<stdin>", line 3, in foo
RuntimeError: maximum recursion depth exceeded
>>>

如果你想耗尽内存,请尝试消耗更多内存。

>>> def foo(l):
...     l = l * 100
...     foo(l)
...
>>> foo(["hello"])
Traceback (most recent call last):
  ...
  File "<stdin>", line 2, in foo
MemoryError
>>>

如果您将代码更改为

i = 0
def foo ():
    global i
    i += 1
    print i
    try :
        foo()
    except RuntimeError :
        # This call recursively goes off toward infinity, apparently.
        foo()
    finally:
        i -= 1
        print i

foo()

你会发现输出振荡低于999(1000是Python的默认递归限制)。 这意味着,当达到限制( RuntimeError )时, foo()最后一次调用终止,另一个被设置为立即替换它。

如果您引发KeyboardInterrupt您将观察整个跟踪是如何立即终止的。


UPDATE

有趣的是foo()的第二次调用不受try ... except -block的保护。 因此,应用程序最终将终止。 如果将递归限制设置为较小的数字,例如sys.setrecursionlimit(3)的输出,这将变得很明显:

$ python test.py
1
2
1
2
1
0
Traceback (most recent call last):
  File "test.py", line 19, in <module>
    foo()
  File "test.py", line 14, in foo
    foo()
  File "test.py", line 14, in foo
    foo()
RuntimeError

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM