In this video, we’ll talk about return statements and recursion.
In a previous video, we talked about how the value that you get from a function is the return value.
If I call type(4), I get the return value of int.
How does the type() function return the type int value?
Let’s write a function that adds two numbers and returns the result the same way how the type() function gets a result.
def add_two_numbers(num1, num2):
result = num1 + num2
Notice how the function uses the same format that we’ve learned in the last video, but there’s a new line that we haven’t seen before.
What return result does is that it gives the value, result, to where the function called.
x = type(4) returns type int.
y = add_two_numbers(1, 2) returns 3.
The return statement also ends the function.
The reason why I bring up return statements here is that you can use the return keyword inside a conditional, and it ends the function.
Let’s change our function a little bit.
def add_two_positive_numbers(num1, num2):
if (num1 < 0):
print("num1 is negative")
elif (num2 < 0):
print("num2 is negative")
result = num1 + num2
print("num1 and num2 are added")
If I were to call add_two_positive_numbers with:
x = add_two_positive_numbers(-1, 1)
I get the print message, num1 is negative.
I also get a return value of None because return stopped the program after the print(“num1 is negative”).
return can be used to exit the function. If there is no return value, you get a None, which means like it implies: nothingness.
Using returns with conditionals will help you limit your function to a specific behavior like what we did: adding only two positive numbers.
In a previous video, we used a function that we created inside another function.
Whenever we used the print function inside of our functions, we are using a function inside of a function.
Let’s talk about recursion. What is recursion? Recursion is the term used when a function calls itself.
Instead of a function calling a different function, the function calls itself.
A function triggering itself inside the function?
You might be thinking that triggering the function in itself would lead to an infinite loop of the function triggering itself.
You use a conditional that stops the function when you’re ready. A conditional that stops a function calling itself is called the base case.
The base case is the way that a function calling itself can stop.
For example, let’s say that we wanted to make a countdown function celebrating the new year.
if (num == 0):
next_num = num - 1
We are making a countdown from 10 to 0 for New Year’s!
10, 9, 8, and so on until we get to 0.
When we hit 0, it’s New Year’s, so when num is 0, we stop the function.
If num is not 0, we countdown again bring the num down 1 number.
We start at 10, 10 is not 0, so display the current num, and go to the next num, which is 9.
We are calling countdown function again, but with one less num.
You can notice that there are two main parts to recursion.
The first part is progress.
We make sure that there is some sort of progress every time we use the function again.
In the example, we decrease the number that we’re using by 1.
The number is perpetually decreasing, which means that there is progression towards an end.
The second part is base case.
We make sure that the a base case occurs at our goal. When we countdown from 10, we want to countdown to 0 eventually.
The number 0 is our end goal.
We use a if statement to check if our number is 0 yet, so that we can just stop calling the function over again.
If we don’t call the function, countdown again, the function stops because there is nothing else in that if statement to do except for displaying “New Years!”
Any recursion can be done iteratively. What is iteratively?
Iteratively means repeating a process one at a time. Doing things manually one at a time.
We are using the print function manually or iteratively one at a time to print three empty lines.
Any iteration can be done recursively and use recursion.
Recursion takes a moment to think about.
Remember that there are two parts.
Part 1) Progress.
Part 2) Base case. The end point.
Decreasing a number or increasing a number is usually a good way to make progress.
The function calling the function must make progress.
A usual base case is checking for 0.
We want to print 3 new lines, so let’s use the number 3 as our argument to act as our starting point.
To make progress, let’s decrease the number 3 each time we use the function.
To end the function, let’s check if the countdown reaches to 0, because if we count from 3 to 0, we should have printed 3 new lines.
Checking if the number is 0 will be our base case, the end point.
if (num > 0):
recursion_print_num_lines(num - 1)
3 is greater than 0, print a new line.
3 – 1 = 2
2 is greater than 0, print a new line.
2 – 1 = 1
1 is greater than 0, print a new line.
1 – 1 = 0
0 is not greater than 0, do nothing, which stops the function because there is nothing left to do.
You might be thinking: When do I use recursion and when do I use iteration, writing each line one by one? Why even use recursion?
Recursion is an important concept to understand because some very specific problems are much easier to solve with recursion.
For example, the Fibonacci sequence. Fibonacci numbers are a sequence of numbers in which each number is the sum of the two preceding numbers.
This problem is easier to solve with recursion than iteration. It’s a very specific problem, which happens to be easier to solve with recursion.
The majority of the time if you’re not dealing with a specific type of problem that works well with recursion, you should use iteration instead and write the repeated lines of what you want to do like how we printed 3 new lines by writing print() function 3 times.
Let’s talk about the cons of recursion.
Number 1) For Python, recursion is slower than iteration.
Speed is a huge turn off when using recursion. Think about speed.
Number 2) You may get confused in making your recursive function because often times, you might think hmmmm at step 5,
I am expecting the number to be this, and I think that if the progress keeps happening, the number will be what I expected.
It’s harder to write a good recursive function.
Number 3) Recursion uses more memory.
With all those cons, why would you even use recursion?
The main advantage of recursion is when you have a very specific problem that has a point A and a point B, and you need to get to point B, but to get to point B requires a large number of complex repetitive steps.
Recursion might be for you. In this very specific situation like Fibonacci numbers, recursion is absolutely the choice to use.
I would recommend to Google for some advice to see if recursion would be great for your very specific problem.
The ultimate rule to is if you ever think that writing your steps iteratively is hard, see if recursion will be easier.
If writing your steps iteratively is easy, then use iteration.
For example, in our countdown problem, counting down from 10 to 0, it’s easy to make.
We can easily print the countdown from 10 to 0. Since it’s easy to make, we should use iteration.
We learn recursion because you will encounter those very specific problems where recursion is the best or only way to solve the problem!
The last topic that we’ll talk in this video is infinite recursion.
Infinite recursion is the term used whenever the function keeps calling itself and never stops.
There’s no base case. There’s no end point.
We can write a new function:
There is no if statement base case that stops the program. All this program does is call itself again and again and again.
Python has an error called Maximum recursion depth exceeded that stops the function from calling itself infinite times.
If there was no Python error to stop the recursive function, the function would call itself until we wouldn’t have any more memory.