Functions¶
1. What are functions and why do we need them?¶
Lets say that you are watching TV. Every time you want to change the channel, you will use the same remote control. It would be quite inconvenient if you had to make a new remote control each time you wanted to change the channel. Similarly, in programming, you might want to write a piece of code that you need to re-use multiple times in different parts of your program.
For example, lets say that you write a program to find the largest number in a list:
1 2 3 4 5 6 7 |
|
But what if you need to find the largest value in 10 different lists? Would it be feasable to rewrite the same code again 10 different times? This is where functions come into the picture. They allow you to re-use the same piece of code again and again, however many times you might want.
More formally, A function is a block of code that allows you to to perform a specific action. It is modular, and re-usable as many times as you want. Some functions might even give you back a value.
For example, the same code written using functions would look something like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
A function does not have to necessarily return a value:
1 2 3 4 5 6 7 8 9 10 11 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Why does it print a None
between the elements of the lists? Remember, these functions don't return any values! Thus, print(displayElementsOf(list1))
doesn't actually have something to print!
Functions are Minimalist
A function does not execute the rest of its code if a return statement is encountered
1 2 3 4 5 |
|
1 |
|
Write a function to calculate the factorial of a number. Use the function to then find the factorials of all the numbers from 1 to 20
What's a factorioal again?
The factorial of a number n, represented by n! is given by: \(n! = n\cdot(n-1)\cdot(n-2)...1\). For example, \(5! = 5\cdot4\cdot3\cdot2\cdot1 = 120\) and \(0! = 1\).
Write a function to calculate the factorial of a number. Use the function to then find the factorials of all the numbers from 1 to 20
What's a factorioal again?
The factorial of a number n, represented by n! is given by: \(n! = n\cdot(n-1)\cdot(n-2)...1\). For example, \(5! = 5\cdot4\cdot3\cdot2\cdot1 = 120\) and \(0! = 1\).
1 2 3 4 5 6 7 8 |
|
2. Type Hints¶
When writing functions with a lot of parameters and variable names that might be unintuitive, it is a good idea to use type hints! type hints allow the person writing the function to tell the user what the expected data types of all the arguments being passed into it are
For example:
1 2 3 4 5 6 |
|
3. What is recursion, and why do we need it?¶
Lets take the factorial from the previous excersie as an example.
We have learnt that n! = n*(n-1)*(n-2)*...*1
Similarly, (n-1)! = (n-1)*(n-2)*...*1
But, notice that from these two equations we can actually write that n! = n*(n-1)!
So if you were being introduced to the factorial for the first time, and you were just told that n! = n*(n-1)! would this be enough information to find out the factorial of any number? Try computing 3! just by using the definition that n! = n*(n-1)!.
If you actually tried to do that, you would realise that its actually not possible because with that definition, you don't know when to stop!
3! = 3*2!
2! = 2*1!
1! = 1*0!
0! = 0*(-1)!
...
This means that other than the fact that n! = n*(n-1)! we also need a point to stop at. Lets say that you are now told that 0! = 1. With that information in mind, we can actually compute 3!
3! = 3*2!
2! = 2*1!
1! = 1*0!
and now, we know that 0! = 1, so now we use that in the last equation and work our way back up!
1! = 1 and then using this, 2! = 2, and then using this, it is found that 3! = 6
This process of defining a process in its own terms is known as recursion! The "stopping point" at which we stop going down and start to work back up is known as the base case! So can we do something like this with functions? Yes!
1 2 3 4 5 6 7 8 9 |
|
What does the following piece of code output? You are not allowed to type this into an IDE and run the code. Try to work it out by hand!
1 2 3 4 5 6 7 |
|
If you need help, but don't want to see the full solution immediately, click "Hint"
What does the following piece of code output? You are not allowed to type this into an IDE and run the code. Try to work it out by hand!
1 2 3 4 5 6 7 |
|
If you need help, but don't want to see the full solution immediately, click "Hint"
Hint: A function will always execute ALL of its code UNLESS a return statement is encountered. If another function call is encountered inside a function, it will first complete the code of that function before continuing with the rest of its own code.
What does the following piece of code output? You are not allowed to type this into an IDE and run the code. Try to work it out by hand!
1 2 3 4 5 6 7 |
|
If you need help, but don't want to see the full solution immediately, click "Hint"
Hint: A function will always execute ALL of its code UNLESS a return statement is encountered. If another function call is encountered inside a function, it will first complete the code of that function before continuing with the rest of its own code.
Output:
1 2 3 4 5 6 7 |
|
4. Exceptions¶
Exceptions are problems that a program might run into during its execution. Take division as an example:
1 2 3 4 |
|
What happens if we try to run this code?
1 2 3 4 5 6 7 8 |
|
Our program crashes (nothing further is executed) when the error is encountered and python yells at us for trying to divide by 0. ZeroDivisionError
is an exception.
4.1. The raise
statement¶
So, how do we make use of Exceptions ourselves? If you have a custom operation that might give an error for certain inputs, we can do that as follows:
1 2 3 4 5 6 7 8 |
|
4.2. The try except else finally
statement¶
Now it would be very inconvenient if every time a program ran into an exception, it just crashed without doing anything else. It is the programmer's job to ensure that errors are dealt with and that they do not make a program crash. How does one deal with errors then?
We use the try except
statement:
1 2 3 4 5 6 7 8 |
|
Catch Me If You Can!
In other languages, except
is often called catch
, and you might hear programmers referring to except
as catch
, they are the same thing!
Now this does not mean that the program is safe, sometimes a single function call raises different errors for different problems, each one of them must be handled:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Sometimes, you might want to run a piece of code regardless of any errors occurring in a try block.
1 2 3 4 5 6 7 |
|
This program still crashes, but it prints finally
before doing so.
If you might want to run a piece of code only when an error did NOT occur, that can be achieved by adding an else
:
1 2 3 4 5 6 7 8 9 10 |
|
You might say that it is equivalent to:
1 2 3 4 5 6 |
|
else
is preferred, because we do not want to unintentionally catch exceptions produced by the rest of the code!
Consider the following example:
1 2 3 4 5 6 |
|
If we used an else
, our intentions would be more explicit!
Error vs Exception
Keen readers would've noticed that the word Exception has been used in the heading of this section, but the examples contain things python calls "Error"s
What is the difference between an Error and an Exception?
Technically, there is none. However, conventionally, an error should never be caught and handled at runtime, they should be prevented to begin with. Exceptions are the ones which are meant to be caught at runtime, but for educational purposes and keeping things simple in the examples above, an Exception to this convention has been made in this article.
This is not a well known convention, and it is common to run into code where errors are used incorrectly on the internet.