[MUSIC] Sometimes when we are writing a program, we find ourselves repeating some code. And we may want to be able to reuse it in different parts of the program. Or we may just want to separate some code from the rest of the program to make the program a little easier to understand. In different programming languages, this separated code is know as subroutine, or procedure, or method. But in Python, we call it a function. A function is named piece of code that can take some input which we call arguments, and produce some output which we'll call the return value. We've already been using functions in our Python examples. These are pieces of code that someone else wrote and have been made available to you as part of the Python programming language. Print is defined as part of the language. Its inputs or arguments are the things to print separated by commas. It prints them and does not have any output or return values. Append is defined as a function that's associated with a list. We specify which list and the function's input is the thing to add to the list. It adds it to the end and doesn't have any output either. Pop is defined as a function that's also associated with a list. Its input is the index of the thing to remove. It removes it and returns that thing as the output. And previously we saw max. Max is also part of the programming language and returns the max value of a list. When we want to create and use our own functions in our code, there are two things we need to do. The first is to define the function which means specifying its name, the names of its inputs or parameters, and what it does. This is where we would write the code that implements the functionality. After we've defined the function, we say that we call or invoke the function by specifying or passing specific inputs or arguments to use. And then indicating which variables should hold any return values or outputs. Let's start with a simple example of a function that calculates the hypotenuse of a right triangle. Using some code we saw a few lessons ago that calculates the square root of A squared plus B squared. Here we start the definition of our function. The key word def indicates that we're defining the function. We're just providing its definition but not actually calling or invoking or running it just yet. This is followed by the name of the function which must be a valid Python identifier name, like variables, and should of course be meaningful. Following the name is a list of the inputs which are comma separated in parentheses. These are known as the parameters. These are variables that will be initialized with the values that are passed inputs or arguments when the function is called. The code or the body of the function is indented to indicate that it is part of the function definition. And of course it can be more than one line of the code. The keyword return indicates that this is the output or return value of the function. Below we have the rest of the program that's going to use this function. Keep in mind that we must define the function before we use it. We invoke the function using its name and specifying the inputs or arguments. When the function is called, the parameter a will hold the value 3 and b will hold the value 4. Then we will do the math and return 5. This value is the output and it is stored in the variable C which we print here. Note that a and b only exist up here in the definition of the function. For example, if you tried to print a and b after calling the function Python would give you an error, because only c has been declared down here. This is known as scope and refers to where our variable lives or can be accessed. We can also pass variables as arguments. Up here we have the same code as the previous slide, but in this case we're going to have variables x and y set to 3 and 4, and then we'll pass x and y as the arguments to the function. When the function is called, the parameter, a, will hold the value that x holds which is 3. In the parameter b, will hold the value that y holds which is 4. Again, we print 5. This is the exact same thing as the previous example where I passed 3 and 4 as the arguments. Now previously we said that a and b only live with inside this function, but we can define variables with the same name outside of the function in a different scope. This can be confusing to the person who reads your code, but sometimes is inevitable. So down here, we defined a variable called a, which we've set to 20. But the variable a that's in the function, the parameter up here, is different from the one down here that's outside the function. In this case, when we call the function the parameter a is set to a 100, but this does not change the variable a that was defined outside the function. So when we print a down here it's still 20 because it's the one defined here, not the one up here. So why use functions? I guess there are two main reasons. First, functions allow us to break up our program to smaller pieces of code which makes it easier to read and understand. But perhaps more importantly, we want to avoid duplicating code. So we only have to write it in one place and can reuse it over and over again. This is code we saw on the previous lesson. It determines whether the list called ages is sorted. It only works for the list called ages. And if we wanted to reuse it, we'd have to make a copy of this code for a different list. This would make our code longer and would result in a lot of duplicated code that may introduce errors. Now here's that same code, but to find as part of a function. At the top here we have the keyword def indicating that I'm defining the function which I've called is_increasing. The input or parameter is called my list. The rest of this code is more or less the same as before. But rather than printing is sorted or is not sorted, I'll use the is sorted variable as the output or return value, so that the code that calls this function can know whether the list is or is not sorted. So now I'm going to use that function. This is the list we saw previously and I'm going to pass it to the argument is increasing. The function now refers to the ages list as my list and runs this code which is the body of the function. It's not sorted, so this line will print false. But now I have a different list called names. And even though it's a list of strings and not numbers, I can still use the is increasing function. And I don't have to rewrite that function for a different list. Rather, when I call or invoke the function this second time, the my list parameter now refers to names. So it runs the same algorithm, but a different input. And in this case it would consider the list to be sorted, because it compares the strings like you would in a dictionary. In these examples, we've seen that the function returns a single value. This can be a number, a string, a boolean, or even a list. But what if we want a function to return more than one thing, like if we have a list and wanted to find not just the largest value, but the three largest values. So here is the function that will find three largest numbers in a list. Because we are going to want to modify the list, as you will see in a second, we are going to make a copy of it first using this copy function. This is so that the code that calls this function doesn't have to worry about this function modifying the list that it passed as an argument. Then we can figure out the largest by using the max function. And we'll call that max1. Then we'll remove max1 from the copy of the list. This is so that we don't double count it. Now we can do that again and find the next biggest value, that is the biggest value in the list that's leftover and we'll call that max2. W'll remove it, and do it again for max3. When we get to the end of the function we know that max1, max2, and max3 are the 3 largest values in that order. In order to return them all together as the single output of this function we put them into what's called a tuple. You can think of a tuple as a temporary collection of values that we use when we want a function to return more than one thing. So now down here, we're going to use that function. So we'll create a list as the input. And when we call the function, we can use the variables first, second and third to hold the three return values that were grouped together into the tuple. You might wonder, why didn't we just return a list of the three largest values? Why do we need this other thing called a tuple? The answer is partly based on technical reasons and partly based on stylistic reasons. We could return a list there, but stylistically, a piece of Python code should only return a list when the thing it's returning is supposed to be a list and not a workaround as a way of returning multiple things. From a technical point of view, if we return a list, the code that called our function could add or remove elements which may not be what we want. In this case, we want it to only contain the three largest elements, nothing more and nothing less. So a tuple is more appropriate. In this lesson, we've talked a little bit about making our code easier to understand by using functions which are named pieces of code that are separated from the rest of the program. When we use our own function in a program, we first need to define it, specify its name and what it does, and then we can call it or invoke it elsewhere.