装飾された再帰関数がどのように機能するかを理解するのに苦労しています。次のスニペットの場合:
def dec(f):
def wrapper(*argv):
print(argv, 'Decorated!')
return(f(*argv))
return(wrapper)
def f(n):
print(n, 'Original!')
if n == 1: return(1)
else: return(f(n - 1) + n)
print(f(5))
print
dec_f = dec(f)
print(dec_f(5))
print
f = dec(f)
print(f(5))
出力は次のとおりです。
(5, 'Original!')
(4, 'Original!')
(3, 'Original!')
(2, 'Original!')
(1, 'Original!')
15
((5,), 'Decorated!')
(5, 'Original!')
(4, 'Original!')
(3, 'Original!')
(2, 'Original!')
(1, 'Original!')
15
((5,), 'Decorated!')
(5, 'Original!')
((4,), 'Decorated!')
(4, 'Original!')
((3,), 'Decorated!')
(3, 'Original!')
((2,), 'Decorated!')
(2, 'Original!')
((1,), 'Decorated!')
(1, 'Original!')
15
最初のものは f(n) を出力するので、当然 f(n) が再帰的に呼び出されるたびに 'Original' を出力します。
2 番目のものは def_f(n) を出力するため、n がラッパーに渡されると、f(n) が再帰的に呼び出されます。ただし、ラッパー自体は再帰的ではないため、「Decorated」は 1 つだけ出力されます。
3 つ目は私を困惑させます。これはデコレータ @dec を使用するのと同じです。装飾された f(n) がラッパーを 5 回も呼び出すのはなぜですか? def_f=dec(f) と f=dec(f) は、2 つの同一の関数オブジェクトにバインドされた 2 つのキーワードにすぎないように見えます。装飾された関数に装飾されていない関数と同じ名前が付けられている場合、何か他のことが起こっていますか?
ありがとう!