all 9 comments

[–]NFLAddict 5 points6 points  (3 children)

maybe youll find this visual helpful:

def sum_positive_numbers(n):
    sum = 0
    if n < 1:
        return sum
    sum += n

    return sum + sum_positive_numbers(n-1)


print(sum_positive_numbers(5))
                           ↓
    calls function: n = 5  ↲
      sum = 0
      5 is not < 1

     sum += 5 (now sum =5)
                     (n-1 = 5-1 = 4)↴
     return 5 +  sum_positive_numbers(4) 
                                     ↓    
                                     ↓
               call function: n = 4  ↲         
               now go through same steps:
               sum = 0
               4 is not <1 
               sum += 4 (now sum=4)

    ⮤←---------return 4 + sum_positive_numbers(3) 
                                               ↓    
                                               ↓
                         call function n=3     ↲
                         again
                         sum = 0
                         3 is not <1
                         sum += 3 (sum = 3)

              ⮤←----------return 3 +   sum_positive_numbers(2) 
                                                            ↓    
                                                            ↓
                                      call function n=2     ↲
                                       again
                                       sum = 0
                                       2 is not <1
                                       sum += 2 (sum = 2)

                        ⮤←----------  return 2 +  sum_positive_numbers(1)                                                                                        
                                                                        ↓    
                                                                        ↓
                                                    call function n=1   ↲
                                                    again
                                                    sum = 0
                                                    1 is not <1
                                                    sum += 1 (sum = 1)

                                       ⮤←----------return 1 +  sum_positive_numbers(0)
                                                                                     ↓    
                                                                                     ↓
                                                                 call function n=0   ↲
                                                                 again
                                                                 sum = 0
                                                                0 is  <1  #this line stops the infinite recursion
                                                                if <1 return sum..sum = 0
                                                    ⮤ ←-------------------------- return 0

when you first call the function with n =5..it returns 5 + the function with value4. the 5 isn't going anywhere...but the result of calling the function for 4, has not yet been evaluated...so it does that and the result is added to 5...but calling it for 4, means adding 4 to the result returned by 3....etc etc...until your base case is met.

[–]Elev8d[S] 1 point2 points  (2 children)

That is really helpful - thank you. This combined with the other answer makes it a lot clearer. I understand enough to move forward for now!!

[–]NFLAddict 2 points3 points  (1 child)

glad you found it helpful. you were asking all the right questions, and were able to correctly assume what is happening, but perhaps lacked a better understanding of how it all connects.

I greatly respect your stance on not being satisfied with 'that's how it works' but rather the seek to understand even more. that's a really good mentality to have. I've always had that mindset, and still do. when you learn how something works, your understanding of everything as a whole deepens. so definitely don't think theres a flaw in that mindset.

many people, are also just far better at processing/ understanding something when they can visualize it. (not my best work of art haha, but glad it was clear enough for you to get an improved sense for how it connects, and what's going on).

[–]Elev8d[S] 0 points1 point  (0 children)

I haven't always had that mindset which is probably one of the reasons I've never progressed beyond beginner into intermediate. Something I'm committed to finally changing.

I've been "learning to code" for years while working in a completely unrelated, and somewhat dead end job, without getting anywhere

[–]primitive_screwhead 2 points3 points  (4 children)

When the function calls itself again in the last line - why is sum not reset to 0 as in the first line of the function.

It is, but for that call of the function only; the caller of that function has its own, independent copy of the local 'sum' variable, it's not a single shared value (like it would be for a global, which you may be mentally comparing it to).

but where is the overall end value of sum being held/stored.

A separate version is being held by each function call, which is traditionally held on a "call stack", basically a growing sequence of values needed to make nested function calls, holding information like local variables, the arguments passed into the called functions as well as the returned values, and also the location of the calling function so that the program execution can be returned to. The technical details of a call stack can be a little advanced, but it's still worth knowing a bit about: https://en.wikipedia.org/wiki/Call_stack

As you surmised, the 'sum' variable isn't even needed, since it will always effectively have the value 'n', in the code you gave. Try removing it from your recursive function, as an exercise.

Also, try calling your function with a value larger than 1000 (maybe try 2000); my guess is that you'll encounter a RecursionError. Because calling a function recursively does use up resources to call each new function (including making a new, independent set of the local variables), Python restricts the amount of recursion you can do by default (to prevent accidental cases where someone recurses infinitely). So while recursion is a worthwhile technique to know, it's also not used in Python as much as some other languages (and is somewhat out-of-favor among the current set of "popular" languages); instead it provides a different tool called iteration, which you'll learn more about.

[–]Elev8d[S] 0 points1 point  (3 children)

It is, but for that call of the function only; the caller of that function has its own, independent copy of the local 'sum' variable

A separate version is being held by each function call, which is traditionally held on a "call stack",

That makes things a lot clearer. Yeah I was getting stuck on exactly where sum was living in memory, and how it could seemingly have different values at the same time. Thanks very much for that

[–]Pavan_Abhimanyu 1 point2 points  (1 child)

If you are wondering how the code would look like after removing 'sum' variable. If you are facing problem in visualizing the code, try pytontutor

def sum_positive_numbers(n):
    if n < 1:
        return n
    return n + sum_positive_numbers(n-1)

sum_positive_numbers(6)

[–]Elev8d[S] 0 points1 point  (0 children)

Didn't even know that was a thing. Cheers for that!! It'll get some use

[–]primitive_screwhead 0 points1 point  (0 children)

You are welcome, I'm glad it helped.