Functions
We’ve been working with functions in python since lesson 1. Throughout this course, you’ve had to use a variety of functions to do things like type conversion, create iterables, print information to the screen, etc. Here, we will look a little more deeply into what is happening when you use a function and also learn how to create our own functions.
Three main concepts
Simply put, functions are a subset of code that has been isolated from a main program, presumably, because that code will be called multiple times throughout the main program. Take the print() function as an example. When you use this function, there is actually quite a bit going on behind the scenes to make it so that the information that you want to be printed is in fact printed. Because this is such a common thing to do in programming, there is a built-in function to make it as easy as
possible.
There are three main concepts that I want you to understand regarding functions: function arguments, return values, and variable scope.
Arguments
When we are using a function (which is called “calling a function”), often, we have to provide that function some information so that it can do its job. The information that we send into the function from the calling program are called arguments. We can use the print() function as an example:
[10]:
print("Hello world!")
Hello world!
The argument that we passed to the print() function is the string “Hello world!”, and print() used that information to send a message to the screen. Many (most?) functions can take more than one argument, and each argument must be separated by a comma.
[11]:
print("The result of 10+6 is",10+6)
The result of 10+6 is 16
Here, two arguments were passed to the print function but we could do more if we wanted to. The number of arguments passed to a function (and their data type) depend on the function itself, so you have to know what a function is doing and some basic information about it to be able to use it properly.
Let’s take a look at a different function to see what can go wrong if we use a function somewhat naively. Let’s say we wanted to convert 2 floats to integers with a single call to the int() function:
[12]:
int(5.6,10.2)
-------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-12-808ff9ffe901> in <module>
----> 1 int(5.6,10.2)
TypeError: 'float' object cannot be interpreted as an integer
This action will result in an error being thrown not because int can’t handle multiple arguments, but rather, it is expecting something different for the second arguement. Specifically, int() expects to receive 0 or 1 positional arguments and 0 or 1 keyword arguments. Positional arguements are all of those that we’ve used so far in this course. The are a single object or single variable. They work with functions because the function will use the argument’s position to determine how to
use it. Keyword arguments, on the otherhand, are specified with a specific function dependent keyword. An example:
[13]:
int('0b1010',base=2)
[13]:
10
In this example, I’m converting a binary number, ‘0b1010’, into decimal (base 10). I had to tell python that ‘0b1010’ is infact a binary number using the keyword argument “base=2”. Here ‘0b1010’ is a positional argument (in the 0th position) and base=2 is a keyword argument. In the guts of the int() function definition, down in the bowels of the basic functionality of python, there is some code that looks for the keyword “base” and if it sees that word in the function call, it assigns the
value that comes after the equal sign to the variable called “base” in the definition itself. Since python is watching for a specific keyword, functions that have multiple keywords defined can have keyword arguments passed in any order. We’ll revisit this concept shortly.
If this all is a bit confusing, that’s ok. We’ll see some more examples as we learn how to create our own functions below. For now, know that when we call a function, we generally need to pass arguments to it so it can complete its job. Note that many functions don’t require any arguments to work! exit() and breakpoint() are two examples that you may have seen before.
Return values
When a function gets called and does it job, it usually has to send information back to the calling program. Whereas an argument enables us to pass information from the main program to the function, a return value is the mechanism for getting information from the function back to the main program. Again, int() provides a good example:
[14]:
int(20.2)
[14]:
20
The argument that we passed was the value 20.2, but the return value was 20. Generally, functions will only return a single object, but note that a single object may contain more than a single piece of information:
[15]:
import numpy as np
print(np.arange(10))
[0 1 2 3 4 5 6 7 8 9]
Here I’m using the arange() function that is part of the numpy module to create a list of 10 integers. arange() only returned a single object (a single list). However, that list can certainly contain many individual values. You will see this behavior a lot in python. Often, a function will return a list with several values, or a dictionary with several key:value pairs.
Scope
Let’s say that you create a variable to store some data, and you want to pass that data into a function and to do something with it:
[16]:
temperature = 100.5
intTemperature = int(temperature)
Again, when I call int(), program flow goes into that function and the lines of code that make up that function are executed like they would be if they were part of the main program. The question is what am I passing to the function? Does int() know about the variable “temperature” or does it just know the value of the temperature value, 100.5? The answer is the latter. Inside the function itself, int() doesn’t know anything about a variable called temperature. int() will
store the value that we pass in, in this case 100.5, in some new variable and use that to perform whatever instructions are in that code. In otherwords, the variable temperature doesn’t have scope inside the int() function. Let’s say that inside int(), the value that we pass in to be converted is called tempvariable. That variable has no scope outside of int(). If I tried to access tempvariable in the main program (by printing it, or doing so math with it) I would get
an error. The main program has no idea that that variable even exists.
The concept of scope is included here as its an important concept to understand when dealing with functions, but the concept itself is a little easier to understand when we start to define our own functions.
Disclaimer
Python is a little bit lazy with scope in one direction. In the above paragraph I said that the temperature variable doesn’t have scope inside a function for which it is an arguement. This isn’t strictly true. If you define temperature in a main program before a function is defined, and then you try to use temperature in that function, it will still have scope inside the function. I only mention this to be completely accurate. But, I think it is better to treat it as if it did not
have scope there, as this is typical behavior in other programming languages. Again, examples will be presented in the lesson on user defined functions.