Whenever you face a problem like this, try to express the result of the function with the same function.

In your case, you can get the result by adding the first number with the result of calling the same function with rest of the elements in the list.

For example,

listSum([1, 3, 4, 5, 6]) = 1 + listSum([3, 4, 5, 6])
                         = 1 + (3 + listSum([4, 5, 6]))
                         = 1 + (3 + (4 + listSum([5, 6])))
                         = 1 + (3 + (4 + (5 + listSum([6]))))
                         = 1 + (3 + (4 + (5 + (6 + listSum([])))))

Now, what should be the result of listSum([])? It should be 0. That is called base condition of your recursion. When the base condition is met, the recursion will come to an end. Now, lets try to implement it.

The main thing here is, splitting the list. You can use slicing to do that.

Simple version

>>> def listSum(ls):
...     # Base condition
...     if not ls:
...         return 0
...
...     # First element + result of calling `listsum` with rest of the elements
...     return ls[0] + listSum(ls[1:])
>>> 
>>> listSum([1, 3, 4, 5, 6])
19

Tail Call Recursion

Once you understand how the above recursion works, you can try to make it a little bit better. Now, to find the actual result, we are depending on the value of the previous function also. The return statement cannot immediately return the value till the recursive call returns a result. We can avoid this by, passing the current to the function parameter, like this

>>> def listSum(ls, result):
...     if not ls:
...         return result
...     return listSum(ls[1:], result + ls[0])
... 
>>> listSum([1, 3, 4, 5, 6], 0)
19

Here, we pass what the initial value of the sum to be in the parameters, which is zero in listSum([1, 3, 4, 5, 6], 0). Then, when the base condition is met, we are actually accumulating the sum in the result parameter, so we return it. Now, the last return statement has listSum(ls[1:], result + ls[0]), where we add the first element to the current result and pass it again to the recursive call.

This might be a good time to understand Tail Call. It would not be relevant to Python, as it doesn't do Tail call optimization.


Passing around index version

Now, you might think that we are creating so many intermediate lists. Can I avoid that?

Of course, you can. You just need the index of the item to be processed next. But now, the base condition will be different. Since we are going to be passing index, how will we determine how the entire list has been processed? Well, if the index equals to the length of the list, then we have processed all the elements in it.

>>> def listSum(ls, index, result):
...     # Base condition
...     if index == len(ls):
...         return result
...
...     # Call with next index and add the current element to result
...     return listSum(ls, index + 1, result + ls[index])
... 
>>> listSum([1, 3, 4, 5, 6], 0, 0)
19

Inner function version

If you look at the function definition now, you are passing three parameters to it. Lets say you are going to release this function as an API. Will it be convenient for the users to pass three values, when they actually find the sum of a list?

Nope. What can we do about it? We can create another function, which is local to the actual listSum function and we can pass all the implementation related parameters to it, like this

>>> def listSum(ls):
...
...     def recursion(index, result):
...         if index == len(ls):
...             return result
...         return recursion(index + 1, result + ls[index])
...
...     return recursion(0, 0)
... 
>>> listSum([1, 3, 4, 5, 6])
19

Now, when the listSum is called, it just returns the return value of recursion inner function, which accepts the index and the result parameters. Now we are only passing those values, not the users of listSum. They just have to pass the list to be processed.

In this case, if you observe the parameters, we are not passing ls to recursion but we are using it inside it. ls is accessible inside recursion because of the closure property.


Default parameters version

Now, if you want to keep it simple, without creating an inner function, you can make use of the default parameters, like this

>>> def listSum(ls, index=0, result=0):
...     # Base condition
...     if index == len(ls):
...         return result
...
...     # Call with next index and add the current element to result
...     return listSum(ls, index + 1, result + ls[index])
... 
>>> listSum([1, 3, 4, 5, 6])
19

Now, if the caller doesn't explicitly pass any value, then 0 will be assigned to both index and result.


Recursive Power problem

Now, lets apply the ideas to a different problem. For example, lets try to implement the power(base, exponent) function. It would return the value of base raised to the power exponent.

power(2, 5) = 32
power(5, 2) = 25
power(3, 4) = 81

Now, how can we do this recursively? Let us try to understand how those results are achieved.

power(2, 5) = 2 * 2 * 2 * 2 * 2 = 32
power(5, 2) = 5 * 5             = 25
power(3, 4) = 3 * 3 * 3 * 3     = 81

Hmmm, so we get the idea. The base multiplied to itself, exponent times gives the result. Okay, how do we approach it. Lets try to define the solution with the same function.

power(2, 5) = 2 * power(2, 4)
            = 2 * (2 * power(2, 3))
            = 2 * (2 * (2 * power(2, 2)))
            = 2 * (2 * (2 * (2 * power(2, 1))))

What should be the result if anything raised to power 1? Result will be the same number, right? We got our base condition for our recursion :-)

            = 2 * (2 * (2 * (2 * 2)))
            = 2 * (2 * (2 * 4))
            = 2 * (2 * 8)
            = 2 * 16
            = 32

Alright, lets implement it.

>>> def power(base, exponent):
...     # Base condition, if `exponent` is lesser than or equal to 1, return `base`
...     if exponent <= 1:
...         return base
...
...     return base * power(base, exponent - 1)
... 
>>> power(2, 5)
32
>>> power(5, 2)
25
>>> power(3, 4)
81

Okay, how will be define the Tail call optimized version of it? Lets pass the current result as the parameter to the function itself and return the result when the base condition it met. Let's keep it simple and use the default parameter approach directly.

>>> def power(base, exponent, result=1):
...     # Since we start with `1`, base condition would be exponent reaching 0
...     if exponent <= 0:
...         return result
...
...     return power(base, exponent - 1, result * base)
... 
>>> power(2, 5)
32
>>> power(5, 2)
25
>>> power(3, 4)
81

Now, we reduce the exponent value in every recursive call and multiple result with base and pass it to the recursive power call. We start with the value 1, because we are approaching the problem in reverse. The recursion will happen like this

power(2, 5, 1) = power(2, 4, 1 * 2)
               = power(2, 4, 2)
               = power(2, 3, 2 * 2)
               = power(2, 3, 4)
               = power(2, 2, 4 * 2)
               = power(2, 2, 8)
               = power(2, 1, 8 * 2)
               = power(2, 1, 16)
               = power(2, 0, 16 * 2)
               = power(2, 0, 32)

Since exponent becomes zero, the base condition is met and the result will be returned, so we get 32 :-)

Answer from thefourtheye on Stack Overflow
Top answer
1 of 5
115

Whenever you face a problem like this, try to express the result of the function with the same function.

In your case, you can get the result by adding the first number with the result of calling the same function with rest of the elements in the list.

For example,

listSum([1, 3, 4, 5, 6]) = 1 + listSum([3, 4, 5, 6])
                         = 1 + (3 + listSum([4, 5, 6]))
                         = 1 + (3 + (4 + listSum([5, 6])))
                         = 1 + (3 + (4 + (5 + listSum([6]))))
                         = 1 + (3 + (4 + (5 + (6 + listSum([])))))

Now, what should be the result of listSum([])? It should be 0. That is called base condition of your recursion. When the base condition is met, the recursion will come to an end. Now, lets try to implement it.

The main thing here is, splitting the list. You can use slicing to do that.

Simple version

>>> def listSum(ls):
...     # Base condition
...     if not ls:
...         return 0
...
...     # First element + result of calling `listsum` with rest of the elements
...     return ls[0] + listSum(ls[1:])
>>> 
>>> listSum([1, 3, 4, 5, 6])
19

Tail Call Recursion

Once you understand how the above recursion works, you can try to make it a little bit better. Now, to find the actual result, we are depending on the value of the previous function also. The return statement cannot immediately return the value till the recursive call returns a result. We can avoid this by, passing the current to the function parameter, like this

>>> def listSum(ls, result):
...     if not ls:
...         return result
...     return listSum(ls[1:], result + ls[0])
... 
>>> listSum([1, 3, 4, 5, 6], 0)
19

Here, we pass what the initial value of the sum to be in the parameters, which is zero in listSum([1, 3, 4, 5, 6], 0). Then, when the base condition is met, we are actually accumulating the sum in the result parameter, so we return it. Now, the last return statement has listSum(ls[1:], result + ls[0]), where we add the first element to the current result and pass it again to the recursive call.

This might be a good time to understand Tail Call. It would not be relevant to Python, as it doesn't do Tail call optimization.


Passing around index version

Now, you might think that we are creating so many intermediate lists. Can I avoid that?

Of course, you can. You just need the index of the item to be processed next. But now, the base condition will be different. Since we are going to be passing index, how will we determine how the entire list has been processed? Well, if the index equals to the length of the list, then we have processed all the elements in it.

>>> def listSum(ls, index, result):
...     # Base condition
...     if index == len(ls):
...         return result
...
...     # Call with next index and add the current element to result
...     return listSum(ls, index + 1, result + ls[index])
... 
>>> listSum([1, 3, 4, 5, 6], 0, 0)
19

Inner function version

If you look at the function definition now, you are passing three parameters to it. Lets say you are going to release this function as an API. Will it be convenient for the users to pass three values, when they actually find the sum of a list?

Nope. What can we do about it? We can create another function, which is local to the actual listSum function and we can pass all the implementation related parameters to it, like this

>>> def listSum(ls):
...
...     def recursion(index, result):
...         if index == len(ls):
...             return result
...         return recursion(index + 1, result + ls[index])
...
...     return recursion(0, 0)
... 
>>> listSum([1, 3, 4, 5, 6])
19

Now, when the listSum is called, it just returns the return value of recursion inner function, which accepts the index and the result parameters. Now we are only passing those values, not the users of listSum. They just have to pass the list to be processed.

In this case, if you observe the parameters, we are not passing ls to recursion but we are using it inside it. ls is accessible inside recursion because of the closure property.


Default parameters version

Now, if you want to keep it simple, without creating an inner function, you can make use of the default parameters, like this

>>> def listSum(ls, index=0, result=0):
...     # Base condition
...     if index == len(ls):
...         return result
...
...     # Call with next index and add the current element to result
...     return listSum(ls, index + 1, result + ls[index])
... 
>>> listSum([1, 3, 4, 5, 6])
19

Now, if the caller doesn't explicitly pass any value, then 0 will be assigned to both index and result.


Recursive Power problem

Now, lets apply the ideas to a different problem. For example, lets try to implement the power(base, exponent) function. It would return the value of base raised to the power exponent.

power(2, 5) = 32
power(5, 2) = 25
power(3, 4) = 81

Now, how can we do this recursively? Let us try to understand how those results are achieved.

power(2, 5) = 2 * 2 * 2 * 2 * 2 = 32
power(5, 2) = 5 * 5             = 25
power(3, 4) = 3 * 3 * 3 * 3     = 81

Hmmm, so we get the idea. The base multiplied to itself, exponent times gives the result. Okay, how do we approach it. Lets try to define the solution with the same function.

power(2, 5) = 2 * power(2, 4)
            = 2 * (2 * power(2, 3))
            = 2 * (2 * (2 * power(2, 2)))
            = 2 * (2 * (2 * (2 * power(2, 1))))

What should be the result if anything raised to power 1? Result will be the same number, right? We got our base condition for our recursion :-)

            = 2 * (2 * (2 * (2 * 2)))
            = 2 * (2 * (2 * 4))
            = 2 * (2 * 8)
            = 2 * 16
            = 32

Alright, lets implement it.

>>> def power(base, exponent):
...     # Base condition, if `exponent` is lesser than or equal to 1, return `base`
...     if exponent <= 1:
...         return base
...
...     return base * power(base, exponent - 1)
... 
>>> power(2, 5)
32
>>> power(5, 2)
25
>>> power(3, 4)
81

Okay, how will be define the Tail call optimized version of it? Lets pass the current result as the parameter to the function itself and return the result when the base condition it met. Let's keep it simple and use the default parameter approach directly.

>>> def power(base, exponent, result=1):
...     # Since we start with `1`, base condition would be exponent reaching 0
...     if exponent <= 0:
...         return result
...
...     return power(base, exponent - 1, result * base)
... 
>>> power(2, 5)
32
>>> power(5, 2)
25
>>> power(3, 4)
81

Now, we reduce the exponent value in every recursive call and multiple result with base and pass it to the recursive power call. We start with the value 1, because we are approaching the problem in reverse. The recursion will happen like this

power(2, 5, 1) = power(2, 4, 1 * 2)
               = power(2, 4, 2)
               = power(2, 3, 2 * 2)
               = power(2, 3, 4)
               = power(2, 2, 4 * 2)
               = power(2, 2, 8)
               = power(2, 1, 8 * 2)
               = power(2, 1, 16)
               = power(2, 0, 16 * 2)
               = power(2, 0, 32)

Since exponent becomes zero, the base condition is met and the result will be returned, so we get 32 :-)

2 of 5
3

Early exit is typical for recursive functions. seq is falsy when empty (therefore when there are no numbers left to sum).

Slice syntax allows to pass sequence to recursively called function without integer consumed in current step.

def listSum(seq):
    if not seq:
        return 0
    return seq[0] + listSum(seq[1:])

print listSum([1,3,4,5,6])  # prints 19
🌐
Codecademy
codecademy.com › learn › learn-recursion-python › modules › recursion-python › cheatsheet
Learn Recursion with Python: Recursion: Python Cheatsheet | Codecademy
Given an input of index N, the ... of the Fibonacci function is O(2^N). ... One can model recursion as a call stack with execution contexts using a while loop and a Python list....
🌐
University of Toronto
cs.toronto.edu › ~david › course-notes › csc110-111 › 14-induction-and-recursion › 05-recursive-lists.html
14.5 Recursive Lists
In other words, this definition decomposes a list into its “first” and “rest” parts, and is recursive because the “rest” part is another list. Here’s an example of how you could visualize this representation in Python:
🌐
Readthedocs
understanding-recursion.readthedocs.io › en › latest › 07 Lists of Lists.html
Summing a List of Lists — Understanding Recursion Using Python 1.0 documentation
To illustrate, here is another example, and one where recursion really begins to shine. Say we have a list L of integers, and we want to return the sum. However, some of these integers sit in sublists within L. We can’t use Python’s sum() method, since it requires that the list be ‘flat’ ...
🌐
Reddit
reddit.com › r/learnprogramming › lists and recursion
r/learnprogramming on Reddit: Lists and recursion
September 19, 2022 -

Hi everyone, I’ve been studying python for one year now, but I still have not grasped recursion very well. I can understand the basic fibonacci example, and I understand how the call stack works, but one thing I can’t seem to figure out is how to use lists recursively. I’ve tried to look for some examples on stack overflow, but they were completely unreadable. The code just gets too complicated, and I can’t understand what the program is doing. Could anyone show me an easy example of appending elements to a list while using recursion? Also, are there are any resources that you’d recommend to master recursion? Thank you in advance

🌐
GeeksforGeeks
geeksforgeeks.org › python › recursion-in-python
Recursion in Python - GeeksforGeeks
Recursion is especially useful for problems that can be divided into identical smaller tasks, such as mathematical calculations, tree traversals or divide-and-conquer algorithms.
Published   2 weeks ago
🌐
Real Python
realpython.com › python-recursion
Recursion in Python: An Introduction – Real Python
October 21, 2023 - In fact, essentially the same thing happens in the recursive implementation as well. When you call a function recursively, Python saves the state of the executing instance on a stack so the recursive call can run.
Find elsewhere
🌐
W3Schools
w3schools.com › python › python_recursion.asp
Python Recursion
Remove List Duplicates Reverse a String Add Two Numbers · Python Examples Python Compiler Python Exercises Python Quiz Python Challenges Python Server Python Syllabus Python Study Plan Python Interview Q&A Python Bootcamp Python Certificate Python Training ... Recursion is when a function calls itself.
🌐
Tutorialspoint
tutorialspoint.com › python › python_recursion.htm
Python - Recursion
The we find the midpoint of the list and restrict the checking to either left or right of midpoint depending on whether the desired number is less than or greater than the number at midpoint. The following diagram shows how binary search works − · The following code implements the recursive binary searching technique −
🌐
GeeksforGeeks
geeksforgeeks.org › python-program-to-flatten-a-nested-list-using-recursion
Python Program to Flatten a Nested List using Recursion - GeeksforGeeks
March 14, 2023 - The task is to convert a nested list into a single list in Python i.e no matter how many levels of nesting are there in the Python list, all the nested have to be removed in order to convert it to a single containing all the values of all the ...
🌐
Open Book Project
openbookproject.net › thinkcs › python › english2e › ch11.html
11. Recursion and exceptions — How to Think Like a Computer Scientist: Learning with Python 2nd Edition documentation
They provide a concise and powerful way to describe recursive data structures that are partially composed of smaller and simpler instances of themselves. The definition is not circular, since at some point we will reach a list that does not have any lists as elements. Now suppose our job is to write a function that will sum all of the values in a nested number list. Python has a built-in function which finds the sum of a sequence of numbers:
🌐
Programiz
programiz.com › python-programming › recursion
Python Recursion (Recursive Function)
In this tutorial, you will learn to create a recursive function (a function that calls itself).
🌐
Python.org
discuss.python.org › python help
Python recursion function for newbie - Python Help - Discussions on Python.org
May 20, 2023 - If it’s counting from 0, then the first number should be 1 + (1 -1) = 1, which is in the list. And the next number results in 2 + ( 2- 1) = 3, which is in the list. But 3 + (3 - 1) = 5, which is not in the list. What am I doing wrong? Thanks 🙂 def tri_recursion(k): if(k > 0):...
🌐
Python Forum
python-forum.io › thread-30159.html
Using recursion instead of for loops / list comprehension
So I’ve been learning about symmetric differences between lists which can be accomplished in a number of different ways using for loops, list comprehension, sets the exclusive or carat. Pretty neat stuff. Now I am exploring recursion. Wrapping ...
🌐
Python.org
discuss.python.org › python help
What is the purpose of this recursive function? - Python Help - Discussions on Python.org
August 19, 2023 - Hi all, I’ve been following a Python course from thegreatcourses.com and towards the middle of the 21st lecture, an example of a recursive function is given, and I cannot for the life of me work out why it calls itself …
🌐
Real Python
realpython.com › python-thinking-recursively
Thinking Recursively in Python – Real Python
November 27, 2023 - Keep this limitation in mind if you have a program that requires deep recursion. Also, Python’s mutable data structures don’t support structural sharing, so treating them like immutable data structures is going to negatively affect your space and GC (garbage collection) efficiency because you are going to end up unnecessarily copying a lot of mutable objects. For example, I have used this pattern to decompose lists and recurse over them:
🌐
Pythonspot
pythonspot.com › recursion
recursion in python w3schools - Python Tutorial
Else, it returns the element and a call to the function sum() minus one element of the list. If all calls are executed, it returns reaches the termination condition and returns the answer. Factorial with recursion The mathematical definition of factorial is: n! = n * (n-1)!, if n > 1 and f(1) = 1. Example: 3! = 3 x 2 x 1 = 6. We can implement this in Python using a recursive function:
🌐
freeCodeCamp
freecodecamp.org › news › how-to-sort-recursively-in-python
How to Sort a List Recursively in Python
October 31, 2024 - This is how recursion works: we initialize a base case for a problem at the start of the function and we assume that this function works for small values of the same problem. Then as the final step, we prove that this works for the existing problem. The Merge Sort algorithm works by breaking down an unsorted list into two halves.
🌐
W3Schools
w3schools.com › python › gloss_python_function_recursion.asp
Python Function Recursion
def tri_recursion(k): if(k>0): result = k+tri_recursion(k-1) print(result) else: result = 0 return result print("\n\nRecursion Example Results") tri_recursion(6) Try it Yourself » · Python Functions Tutorial Function Call a Function Function Arguments *args Keyword Arguments **kwargs Default Parameter Value Passing a List as an Argument Function Return Value The pass Statement i Functions