Functions and Conditions
Overview
Teaching: 15 min
Exercises: 15 minQuestions
How do I write functions?
Objectives
Be able to write our own functions and use basic functional programming constructs like
map()
andfilter()
.
Of course, at some point, we are going to want to define our own functions rather than just use the ones provided by Python and its various modules.
The general syntax for defining a function is as follows:
def function(arg1):
# do stuff with arg1
return answer
So, an example function that adds two numbers together might look a little like this:
def adder(x, y):
return x + y
adder(1, 2)
3
We can also add a default argument (say if we wanted y to be equal to 10 unless we otherwise specified), by using an equals sign and a default value in our function definition:
def adder(x, y=10):
return x + y
adder(5)
15
Practice defining functions
Define a function that converts from temperatures in Fahrenheit to temperatures in Kelvin, and another function that converts back again.
The general formula for the conversion from Fahrenheit to Kelvin is:
kelvin = (fahr - 32) * 5 / 9 + 273.15
Conditional statements
We may also need to have our functions do specific things in some conditions, but not in others. This relies upon comparisons between items:
In python, comparison is done using the ==
operator:
True == True
True == False
'words' == 'words'
True
False
True
not
indicates the opposite of True or False, and !=
means not equal to.
not True == False
True != False
True
True
As with other programming languages, we can make the usual comparisons with the
>
and <
operators.
Adding an equals sign (>=
, <=
) indicates less than or equal to or greater
than or equal to.
5 < 10
5 > 10
-4 >= -4
1 <= 2
True
False
True
True
These statements can be combined with the if
statement to produce code that
executes at various times.
number = 5
if number <= 10:
print('number was less than 10')
number was less than 10
If the if
statement is not equal to True
,
the statement does not execute:
number = 11
if number <= 10:
print('number was less than 10')
However, we can add code to execute when the if
condition is not met by
adding an else
statement.
number = 11
if number <= 10:
print('number was less than 10')
else:
print('number was greater than 10')
number was greater than 10
And if we want to check an additional statement,
we can use the elif
keyword (else-if):
number = 10
if number < 10:
print('number was less than 10')
elif number == 10:
print('number was equal to 10')
else:
print('number was greater than 10')
One final note, to check if a value is equal to None
in Python
we must use is None
and is not None
.
Normal ==
operators will not work.
None is None
5 is not None
True
True
Additionally, we can check if one value is in another set of values with the
in
operator:
5 in [4, 5, 6]
43 in [4, 5, 6]
True
False
map(), filter(), and anonymous (lambda) functions
Python has good support for functional programming, and has its own equivalents for map/reduce-style functionality. To “map” a function means to apply it to a set of elements. To “reduce” means to collapse a set of values to a single value. Finally, “filtering” means returning only a set of elements where a certain value is true.
Let’s explore what that means with our own functions. The syntax of map/reduce/filter is identical:
map(function, thing_to_iterate_over, next_thing_to_iterate_over)
Let’s apply this to a few test cases using map. Note that when selecting which function we are going to “map” with,
import math
values = [0, 1, 2, 3, 4, 5, 6]
map(math.sin, values)
<map object at 0x7f31c246cba8>
To retrieve the actual values, we typically need to make the resulting output a list.
list(map(math.sin, values))
[0.0,
0.8414709848078965,
0.9092974268256817,
0.1411200080598672,
-0.7568024953079282,
-0.9589242746631385,
-0.27941549819892586]
filter()
applies a similar operation,
but instead of applying a function to every piece,
it only returns points where a function returns true.
def less_than_3(val):
return val < 3
list(filter(less_than_3, values))
[0, 1, 2]
That was very inconvenient. We had to define an entire function just to only use it once. The solution for this is to write a one-time use function that has no name. Such functions are called either anonymous functions or lamdba functions (both mean the same thing).
To define a lambda function in python, the general syntax is as follows:
lambda x: x + 54
In this case, lambda x:
indicates we are defining a lambda function with a
single argument, x
.
Everything following the :
is our function.
Whatever value this evaluates to is automatically returned.
So lambda x: x + 54
equates to:
def some_func(x):
return x + 54
Rewriting our filter statement to use a lambda function:
list(filter(lambda x: x < 3, values))
[0, 1, 2]
And a side-by-side example that demonstrates the difference between map()
and
filter()
.
list(map(lambda x: x+100, [1,2,3,4,5]))
list(filter(lambda x: x<3, [1,2,3,4,5]))
[101, 102, 103, 104, 105] # map()
[1, 2] # filter()
Using lambdas in practice
Add
'-cheesecake'
to every word in the following list usingmap()
.
['new york', 'chocolate', 'new york', 'ketchup', 'mayo']
Using
filter()
, remove the items which would be absolutely terrible to eat.
map/filter style functionality with Numpy arrays
Although you could use a for-loop to apply a custom function to a numpy array
in a single go, there is a handy np.vectorize()
function you can use to
convert your functions to a vectorised numpy equivalent.
Note that this is purely for convenience — this uses a for-loop
internally.
import numpy as np
# create a function to perform cubes of a number
vector_cube = np.vectorize(lambda x: x ** 3)
vector_cube(np.array([1, 2, 3, 4, 5]))
array([ 1, 8, 27, 64, 125])
To perform a similar option to filter()
,
you can actually specify a conditional statement inside the []
when indexing a Numpy array.
arr = np.array([1, 2, 3, 4, 5])
arr[arr >= 3]
Removing np.nan values
Remove all of the
np.nan
values from the following sequence using logical indexing.
np.array([np.nan, np.nan, 2, 3, 4, np.nan])
Key Points
map()
applies a function to every object in a data structure.
filter()
returns only the data objects for which some condition is true.