装飾された再帰関数がどのように機能するかを理解するのに苦労しています。 次のスニペットの場合:Pythonで再帰関数をデコレートする
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)が再帰的に呼び出される印刷します。
2つ目はdef_f(n)を出力するので、nがラッパーに渡されるとf(n)が再帰的に呼び出されます。しかし、ラッパー自体は再帰的ではないので、「飾られた」の1つだけが印刷されます。
デコレータ@decを使用するのと同じ3番目のものが私を困惑させます。なぜ装飾されたf(n)もラッパーを5回呼び出すのですか? def_f = dec(f)とf = dec(f)は、2つの同一の関数オブジェクトにバインドされた2つのキーワードに過ぎないと思う。装飾された機能に装飾されていない機能と同じ名前が付けられているときには、何か他のことがありますか?
ありがとうございます!
元 'F'関数への参照がまだ存在しているの内側ラッパー内部
func.__name__
とf.__name__
を印刷することで、これを見ることができます。 'f = dec(f)'を実行すると、常に新しい関数が呼び出されます。そして、新しい関数はオリジナルを呼び出します。 – JBernardo'decorator'は実際にデコレータをこの関数に適用することはないので、ここで使用する正しい用語ではないかもしれません。 'f = dec(f)'の最後のテストは '@dec def f'とほとんど同じです(正確でない場合) –