Recursion
Quiz: counts toward finishing the lesson. Check: just for practice.
Introduction
A recursive function is a function that calls itself. Each time it calls itself, a separate copy is created that has its own values for its parameters and variables. If every copy created another copy, the recursion would never end and the computer would run out of memory. So every recursive function needs at least one base case. A base case is a case where the function doesn't call itself.
Let's look at a common first example of recursion:
The if statement checks whether num is equal to zero. This is the base case. If it's true, the function does not call itself. Otherwise, it calls itself, multiplies the return value by num, and returns the result. We could also write it like this:
The else can be left out because if the condition is true, return 1 runs and the function ends before it reaches the recursive call. The other examples in this lesson use this style.
The Call Stack
When a recursive function runs, several copies of it are active at once, but only the most recent one is executing. The others are paused, waiting for a result. When a recursive call is made, the computer saves its place in the current copy so it can come back later, then starts a new copy. It saves that place on the call stack, which keeps track of all active function calls. Watch the video "Flow of execution example for recursion" to see how this works.
Check your understanding. Predict the result. Follow each call down to the base case, then work back up.
def mystery(n):
if n == 0:
return 0
return mystery(n - 1) * 2 + n
x = mystery(3)
y = mystery(1)
Predict what each variable holds after the program finishes. The program is not run for you. Change the values below to your predictions:
final_xis the value ofxat the endfinal_yis the value ofyat the end
Hint 1
Each paused copy finishes its multiply and add only after the call below it returns.
More examples
Here's a recursive function that finds the greatest common divisor of two integers:
The base case is when b evenly divides a, in which case b is the greatest common divisor. Otherwise we make a recursive call, passing b for a and a % b for b. The function just returns whatever the recursive call returns, with no extra work.
Here's a recursive function that computes the hailstone sequence starting from a given number and counts how many steps it takes to reach 1:
Here the base case is when the sequence arrives at 1. There are two recursive cases: one if num is even and one if it is odd. We add 1 to the return value, since the current copy of hailstone takes one more step to reach 1 than the recursive call does. For example, if we start at 3, the sequence goes: 3, 10, 5, 16, 8, 4, 2, 1. Once we know how many steps it takes to go from 10 to 1, we add 1 more step to get the number of steps from 3 to 1.
Writing a Recursive Function
Recursion can feel like magic, because you're writing a function that calls the function you're still writing. The general strategy is to find a way to break the problem into a smaller problem of the same kind, plus a bit of work at the current level.
- In the factorial example,
num! is equal to (num-1)! multiplied bynum. The smaller problem of the same kind is (num-1)!, and multiplying bynumis the bit of work at the current level. - In the gcd example, the gcd of
aandbis the same as the gcd ofbanda % b, which is a smaller problem of the same kind. No additional work at the current level is needed. - In the hailstone sequence example, the smaller problem of the same kind is counting how many steps it takes to get from the next number in the sequence to 1. The bit of work at the current level is adding 1 to that result.
Quizzes
- Write a recursive function called
countdownthat takes a positive integer parameter and returns a string that counts down from that number to 1. For example, if5is passed to the function, it should return the string"5 4 3 2 1". You can use string concatenation in your recursive function to build up the return value.
Hint 1
The base case is when n is 1. Otherwise, put str(n) in front of the result of countdown(n - 1).
- Write a recursive function called
countupthat takes a positive integer parameter and returns a string that counts up from 1 to that number. For example, if5is passed to the function, it should return the string"1 2 3 4 5". You can use string concatenation in your recursive function to build up the return value.
Hint 1
This is the mirror of countdown. Put the result of countup(n - 1) in front of str(n).
- Write a recursive function called
sum_countupthat takes an integer parameter and returns the sum of all the integers from 1 to that number. For example if the function is passed the value5, then it should return15because 1 + 2 + 3 + 4 + 5 = 15.
Hint 1
The base case returns 1 when n is 1. Otherwise add n to sum_countup(n - 1).
- Predict the result. Look at which side of the recursive call each number goes on.
def build_up(n):
if n == 0:
return ""
return build_up(n - 1) + str(n)
def build_down(n):
if n == 0:
return ""
return str(n) + build_down(n - 1)
x = build_up(3)
y = build_down(3)
Predict what each variable holds after the program finishes. The program is not run for you. Change the values below to your predictions, and write strings with quotes:
final_xis the value ofxat the endfinal_yis the value ofyat the end
Hint 1
The recursive call returns a string, and the current number is joined on one side of it.
Projects
Practice what you learned in your own editor. Each project has its own page.