Python 関数f
とfhelp
. fhelp
自分自身を再帰的に呼び出すように設計されています。f
再帰的に呼び出すべきではありません。f
再帰的に呼び出されたかどうかを判断する方法はありますか?
5544 次
2 に答える
16
これには、トレースバックモジュールを使用します。
>>> import traceback
>>> def f(depth=0):
... print depth, traceback.print_stack()
... if depth < 2:
... f(depth + 1)
...
>>> f()
0 File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in f
None
1 File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in f
File "<stdin>", line 2, in f
None
2 File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in f
File "<stdin>", line 4, in f
File "<stdin>", line 2, in f
None
したがって、スタック内のいずれかのエントリが、コードがから呼び出されたことを示している場合f
、呼び出しは(間接的に)直接再帰的でした。このtraceback.extract_stack
メソッドを使用すると、このデータに簡単にアクセスできます。次の例のif len(l[2] ...
ステートメントは、関数の名前と完全に一致する数を単純にカウントします。それをさらに美しくするために(アイデアのagfに感謝します)、デコレータにすることができます:
>>> def norecurse(f):
... def func(*args, **kwargs):
... if len([l[2] for l in traceback.extract_stack() if l[2] == f.func_name]) > 0:
... raise Exception, 'Recursed'
... return f(*args, **kwargs)
... return func
...
>>> @norecurse
... def foo(depth=0):
... print depth
... foo(depth + 1)
...
>>> foo()
0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in func
File "<stdin>", line 4, in foo
File "<stdin>", line 5, in func
Exception: Recursed
于 2011-10-26T08:35:26.443 に答える
3
デコレーターによって設定されたフラグを使用できます。
def norecurse(func):
func.called = False
def f(*args, **kwargs):
if func.called:
print "Recursion!"
# func.called = False # if you are going to continue execution
raise Exception
func.called = True
result = func(*args, **kwargs)
func.called = False
return result
return f
それからあなたはすることができます
@norecurse
def f(some, arg, s):
do_stuff()
f
実行中に再度呼び出されるcalled
と、True
例外が発生します。
于 2011-10-26T08:45:12.797 に答える