A function is a sequence of instructions that has been given a name. Functions usually (but not always) take some number of inputs, called parameters, and usually (but not always) give an output, called the return value. When we use a function in our code, we say that we are calling the function.
Once a function has been defined, it can be called from anywhere within your program. If you find that there is a task that you are repeating often and that requires several lines of codes, it might be a good idea to group those lines of code together into a function.
Most functions we write will accept one or more inputs and will generate an output. However, We will start by considering functions that do not accept inputs, and that do not provide outputs. The syntax for defining such a function is as follows:
def function_name(): Code to be executed by the function.
We start by defining a (very) simple function below.
def greeting():
print("Hello, world!")
Notice that nothing was printed when we defined the function. This cell defined the function, but it did not call it. Thus, the code inside of the function was not executed.
greeting()
for i in range(0,5):
greeting()
The function greeting()
defined above is not vary useful, for a few reasons. In particular, it doesn't accept any inputs. There are occassions when you will want to write functions that take no inputs, but functions are generally more useful when we are able to supply them information that affects how they behave.
When defining a function, we can specify that a function expects one or more inputs by listing variable names between the parentheses to serve as placeholders for the inputs. The placeholders themselves are called parameters, and specific values that are supplied as inputs are referred to as arguments.
In the example below, we create a function square()
that has a single parameter, denoted by n
. When the function is called, an argument must be supplied as a value for this parameter. The function will then print the square of that argument.
def square(n):
print(n**2)
In the cell below, we call the square
function with several different arguments. Each one of these arguments is substituted in for the parameter n
for that particular function call.
square(2)
square(3.6)
square(-3)
If we would like, we can specify the name of the parameter when we are calling a function. This is usually not necessary, however.
square(n=4)
Note that (unlike many languages) Python does not ask us to specifiy what data type the arguments should be. However, if we supply an argument for which the function would perform an illegal operation, we will get an error.
square('circle')
Additionally, if a function has one or more parameters, but we don't supply arguments for those parameters when we call the function, we will get an error.
square()
In this example, we will write a function called square_message()
. The function should take one argument, n
, and should print the message:
The square of [n] is [n**2].
def square_message(n):
print("The square of ", n, " is ", n**2, ".", sep='')
In the cell below, we have a loop that applies the function square_message()
to every element of the list A
.
A = [12, 34, 89, 17, 23, 49, 87, 34, 89, 71]
for i in range(0, len(A)):
square_message(A[i])
All of the function we have written so far have printed some sort of message. However, we will not always desire this sort of behavior. Most of the pre-defined functions we have seen in this course print nothing at all, but instead provide some sort of output that can be printed, or stored into a variable.
For example, the sum()
function takes a list as an input, and provides the sum of the values in the list as the output. When a function provides an output, that output is called a return value.
The syntax for defining a function with a return value is as follows:
def my_function(parameter1, parameter 2, ...):
Code to be executed.
return value_to_be_returned
As a simple example, the cell below defines a function called half()
that accepts a single input, and returns the input divided by 2.
def half(x):
return x/2
y = half(36)
print(y)
half(9) + half(14)
print(half(100))
print(half(35))
print(half(3.14159))
We can nest function calls inside of each other. In this way, the return value for one function call becomes the argument for another.
one_eighth = half(half(half(20)))
print(one_eighth)
n
Positive Integers¶In the following cell, we write a function called sum_first()
that takes a single parameter n
, and returns the sum of the first n positive integers.
def sum_first(n):
total = 0
for i in range(1,n+1):
total = total + i
return total
We now call sum_first()
on 100, and also on 237, printing the return value for each function call.
print(sum_first(100))
print(sum_first(237))
We will now write a function called fact()
that takes in one argument, assumed to be an integer, and returns the factorial of that integer.
def fact(n):
product = 1
for i in range(1,n+1):
product = product * i
return product
We will use our function calculate the factorials of 3, 5, 10, and 20.
print(fact(3))
print(fact(5))
print(fact(10))
print(fact(20))
It is possible for functions to have two or more parameters. Consider the following example.
def power(a, b):
return a**b
print( power(2, 5) )
print( power(3, 4) )
print( power(10, 2) )
print( power(2, 10) )
Notice that when we call a function with multiple arguments, the arguments are assigned to the parameters in the same order as they appear. If we specify names for the parameters when we call a function, then we can supply the arguments in any order that we wish.
print(power(a=4, b=3))
print(power(b=3, a=4))
Supplying names for our parameters can make our code easier to read when we are using functions with many parameters. It can also be useful when we can't recall the exact order in which the parameters appeared in the function definition.
It is sometimes useful to assign a default value to a parameter. This can be done by setting the parameter equal to the desired default value in the function definition. When the function is called, if an argument is supplied for this parameter, it will override the default value. If no argument is supplied for a parameter with a default value, then the default will be used.
def sum_first(arg_list, n=5):
total = 0
for i in range(n):
total += arg_list[i]
return total
my_list = [4, 8, 5, 7, 4, 9, 1, 6, 3, 2]
print(sum_first(my_list, 3))
print(sum_first(my_list, 5))
print(sum_first(my_list))
If the argument supplied for n
in the sum_first()
function is greater than the length of the list, then the function will result in an error. We will now rewrite this function so that it instead retuns the sum of all of the elements in the list in this situation.
def sum_first(arg_list, n=5):
total = 0
m = min(n, len(arg_list))
for i in range(m):
total += arg_list[i]
return total
print(sum_first(my_list, 15))
sum_power
Function¶In the cell below, we create a function called sum_power
. The function has two parameters, x
and n
. The parameter x
is intended to be a list. The parameter n
should be an int
with a default value of 1
. The function should raise each element to the power of n
, sum the resulting values, and then return this sum.
def sum_power(x, n=1):
total = 0
for i in range(0, len(x)):
total += x[i]**n
return total
We test our function in the cell below.
A = [4,-3,1]
print(sum_power(A))
print(sum_power(A, 2))
print(sum_power(A, 3))
print(sum_power(A, 7))
find_item
Function¶In the cell below, we define a function called find_item
that has three parameters, x
, item
, and first
. The parameter x
is expected to be a list. The parameter first
should have a default value of True
. The function should behave as follows:
first == True
, then the function should search for the first time that item
appears in x
, and should return the index of that occurrence.first == False
, then the function should search for the last time that item
appears in x
, and should return the index of that occurrence.item
does not appear in x
, then the function should return None
.def find_item(x, item, first=True):
idx = None
for i in range(0, len(x)):
if x[i] == item:
idx = i
if first:
return idx
return idx
After defining your function, use the following lines of code to test it.
letter_list = ['B', 'C', 'A', 'D', 'A', 'C', 'B', 'A', 'D']
print(find_item(letter_list, 'A'))
print(find_item(letter_list, 'A', first=False))
print(find_item(letter_list, 'D'))
print(find_item(letter_list, 'D', first=False))
print(find_item(letter_list, 'E'))
print(find_item(letter_list, 'E', first=False))
It is possible for a Python function to return multiple values. To To accomplish this, we can combine the desired return values together into a list or a tuple, which we then return. Alternately, we can simply list the return values in the return statement, separated by commas.
When storing the values returned by such a function in variables, we can list the target variable names on the left of the assignment operator, separated by commas.
def power(a,b):
return (a**b, b**a)
a_to_b, b_to_a = power(2,5)
print(a_to_b)
print(b_to_a)
Write a function div_w_remainder()
that takes two arguments, num
and div
, and returns the number of times that div
evenly divides num
(i.e. the quotient), as well as the remainder of num
after division by div
. Coerce the remainder into an integer.
def div_w_remainder(num, div):
quotient = int(num/div)
remainder = num % div
return (quotient, remainder)
We will now consider several examples to test our function.
q, r = div_w_remainder(17, 3)
print('Quotient: ', q)
print('Remainder:', r)
q, r = div_w_remainder(459, 17)
print('Quotient: ', q)
print('Remainder:', r)
q, r = div_w_remainder(6237, 13)
print('Quotient: ', q)
print('Remainder:', r)
Write a function called locate
. The function should take two arguments: a list called x
, and another variable called item
.
The function should return two values: A list of indices at which the element in x
is equal to item
, and a count of the number of times that item
appears in x
.
def locate(x, item):
index_list = []
for i in range(0, len(x)):
if x[i] == item:
index_list.append(i)
return (index_list, len(index_list))
A list of student grades is provided in the cell below. Call locate()
five times. In each function call, pass in grades
for x
. For item
, use each of the following values: 'A'
, 'B'
, 'C'
, 'D'
, and 'F'
.
For each function call, print out a message of the following form:
A: indices = [......], count = ##
grades = ['A', 'D', 'A', 'C', 'B', 'F', 'A', 'D', 'C', 'B', 'F', 'A', 'C',
'B', 'A', 'B', 'B', 'C', 'B', 'F', 'D', 'D', 'A', 'C', 'B']
for letter in ['A', 'B', 'C', 'D', 'F']:
idx, c = locate(grades, letter)
print(str(letter) + ': indices = ' + str(idx) + ', count = ' + str(c) )
It is possible for a function to have multiple return statements. As soon as a return statement is hit, however, the function returns that value and then exits. As an illustration of this idea, compare the following two functions, both of which return the absolute value of a number.
def abs_val_1(x):
if (x < 0):
absVal = -x
else:
absVal = x
return absVal
print(abs_val_1(9))
print(abs_val_1(-3.8))
def abs_val_2(x):
if(x < 0):
return -x
return x
print(abs_val_2(9))
print(abs_val_2(-3.8))