장식 된 재귀 함수가 어떻게 작동하는지 이해하는 데 어려움을 겪고 있습니다. 다음 니펫 :파이썬에서 재귀 함수 장식하기
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)를 출력한다.
두 번째 것은 def_f (n)을 인쇄하므로 n이 래퍼로 전달되면 f (n)을 재귀 적으로 호출합니다. 그러나 래퍼 자체는 재귀 적이 지 않으므로 '장식 됨'이 하나만 인쇄됩니다.
제 3의 퍼즐은 제게 데코레이터 @dec를 사용하는 것과 같습니다. 왜 장식 된 f (n)도 래퍼를 5 번 호출합니까? def_f = dec (f)와 f = dec (f)는 두 개의 동일한 함수 객체에 바인딩 된 단지 두 개의 키워드라고 봅니다. 데코 레이팅 된 기능에 장식되지 않은 것과 동일한 이름이 지정되면 다른 작업이 진행되고 있습니까?
감사합니다.
원래'f' 기능에 대한 참조가 여전히 존재 내부의 래퍼 내부
func.__name__
및f.__name__
를 인쇄하여 볼 수 있습니다. 'f = dec (f)'하면, 항상 새로운 함수를 호출 할 것이다. 그리고 새로운 기능은 원본을 호출합니다. – JBernardo'decorator'는 실제로이 함수에 데코레이터를 적용하지 않기 때문에 여기에서 사용할 올바른 용어가 아닐 수도 있습니다. 'f = dec (f)'의 마지막 테스트는 거의 (정확하게는 아닐지라도)'@dec def f'와 거의 같다. –