I find it hard to understand how a decorated recursive function works. For the following snippet:
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))
Output:
(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
The first prints f (n), so naturally, it prints "Original" every time f (n) is called recursively.
The second prints def_f (n), so when n is passed to the shell, it calls f (n) recursively. But the shell itself is not recursive, so only one "Decorated" is printed.
The third puzzles me, which is similar to using decorator @dec. Why is decorated f (n) also invoking a wrapper five times? It seems to me that def_f = dec (f) and f = dec (f) are just two keywords associated with two identical function objects. Is there anything else when the decorated function is given the same name as the untethered?
Thanks!