6

なぜ/どのようにこれが一見無限ループを作成するのですか?間違って、これが何らかの形のスタックオーバーフロータイプのエラーを引き起こすと思いました。

i = 0

def foo () :
    global i

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

foo()

print i
4

2 に答える 2

6

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
>>>
于 2012-06-27T09:09:42.290 に答える
4

コードを次のように変更すると

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()が終了し、別の呼び出しが開始されてすぐに置き換えられます。

a を上げると、KeyboardInterruptトレース全体が一度にどのように終了するかがわかります。


アップデート

興味深いことに、 の 2 番目の呼び出しは-blockfoo()によって保護されなくなりました。try ... exceptしたがって、アプリケーションは実際には最終的に終了します。これは、再帰制限をより小さな数に設定すると明らかになります。たとえば、次の出力です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
于 2012-06-27T09:19:35.703 に答える