iteration without a loop in python -


the following example "think python" book allen downey. while explaining concept of "memos" in dictionaries, quotes following example.

known = {0:0, 1:1} def fibonacci(n):     if n in known:         return known[n]     res = fibonacci(n-1) + fibonacci(n-2)     known[n] = res     return res fibonacci(5) print known 

i expecting code return {0:0, 1:1, 5:5} since don't see iteration compute function each value between 1 , 5. see {0: 0, 1: 1, 2: 1, 3: 2, 4: 3, 5: 5} returned when code run (as book says would), can't understand why function computed expression res = fibonacci(n-1) + fibonacci(n-2) n=2, n=3 , n=4.

can please explain me? can't quite explanation in book.

try putting print statements code keep track of state of known:

def fibonacci(n):     print(n, known)     if n in known:         return known[n]     res = fibonacci(n-1) + fibonacci(n-2)      known[n] = res     return res fibonacci(5) print(known) 

yields

5 {0: 0, 1: 1} 4 {0: 0, 1: 1} 3 {0: 0, 1: 1} 2 {0: 0, 1: 1} 1 {0: 0, 1: 1} 0 {0: 0, 1: 1} 1 {0: 0, 1: 1, 2: 1} 2 {0: 0, 1: 1, 2: 1, 3: 2} 3 {0: 0, 1: 1, 2: 1, 3: 2, 4: 3} {0: 0, 1: 1, 2: 1, 3: 2, 4: 3, 5: 5} 

the first (integer) value value of n. can see, fibonacci(5) called, fibonacci(4), fibonacci(3), fibonacci(2) , on. these calls due python encountering

    res = fibonacci(n-1) + fibonacci(n-2) 

and recursively calling fibonacci(n-1). remember, python evaluates expressions left right. after fibonacci(n-1) returns fibonacci(n-2) called.

to better understand order of recursive function calls use decorator:

import functools  def trace(f):     """this decorator shows how function called.     useful recursive functions."""     indent = ' ' * 2      @functools.wraps(f)     def wrapper(*arg, **kw):         arg_str = ', '.join(             ['{0!r}'.format(a) in arg]             + ['{0} = {1!r}'.format(key, val) key, val in kw.items()])         function_call = '{n}({a})'.format(n=f.__name__, a=arg_str)         print("{i}--> {c}".format(             i=indent * (trace.level), c=function_call))         trace.level += 1         try:             result = f(*arg, **kw)             print("{i}<-- {c} returns {r}".format(                 i=indent * (trace.level - 1), c=function_call, r=result))         finally:             trace.level -= 1         return result     trace.level = 0     return wrapper  known = {0:0, 1:1} @trace def fibonacci(n):     # print(n, known)     if n in known:         return known[n]     res = fibonacci(n-1) + fibonacci(n-2)      known[n] = res     return res fibonacci(5) print(known) 

which yields

--> fibonacci(5)                            --> fibonacci(4)                        # fibonacci(5) calls fibonacci(4)     --> fibonacci(3)                      # fibonacci(4) calls fibonacci(3)       --> fibonacci(2)                    # fibonacci(3) calls fibonacci(2)         --> fibonacci(1)                  # fibonacci(2) calls fibonacci(1)         <-- fibonacci(1) returns 1         --> fibonacci(0)                  # fibonacci(2) calls fibonacci(0)         <-- fibonacci(0) returns 0       <-- fibonacci(2) returns 1       --> fibonacci(1)                    # fibonacci(3) calls fibonacci(1)       <-- fibonacci(1) returns 1     <-- fibonacci(3) returns 2     --> fibonacci(2)                      # fibonacci(4) calls fibonacci(2)      <-- fibonacci(2) returns 1   <-- fibonacci(4) returns 3   --> fibonacci(3)                        # fibonacci(5) calls fibonacci(3)    <-- fibonacci(3) returns 2 <-- fibonacci(5) returns 5 {0: 0, 1: 1, 2: 1, 3: 2, 4: 3, 5: 5} 

you can tell level of indentation each recursive call coming from.


Comments

Popular posts from this blog

get url and add instance to a model with prefilled foreign key :django admin -

android - Keyboard hides my half of edit-text and button below it even in scroll view -

css - Make div keyboard-scrollable in jQuery Mobile? -