Functions

Functions in Python are like mathematical functions. A function will take some values, do something to them or with them, and return something. Python functions can take any combination of data types and data structures and return a single value that can be any data type or data structure


In [ ]:
# a simple function that looks like a mathematical function
# define a function called add_two_numbers that take 2 arguments: num1 and num2
def add_two_numbers(num1, num2):
    # Under the def must be indented
    return num1 + num2 # use the return statment to tell the function what to return

Use return ... to give a value back to the caller. A function that doesn’t explicitly return a value automatically returns None.

Defining a function does not run it.

You must call the function to execute the code it contains.


In [ ]:
add_two_numbers(905, 90)

In [ ]:
# written a different way
# define a function called add_two_numbers that take 2 arguments: num1 and num2
def add_two_numbers(num1, num2): 
    total = num1 + num2 # do the stuff
    # This is the body of the function
    return total # use the return statment to tell the function what to return

result = add_two_numbers(905, 90)
print(result)
print(add_two_numbers(905, 90))

Question 00

What does the following program print? (Don't actually code, just think about it.)

def report(pressure):
    print(‘pressure is: ’, pressure)

report(22.5)

Practice 00

“Adding” two strings produces their concatenation: 'a' + 'b' is 'ab'. Write a function called quote that takes two parameters called original and wrapper and returns a new string that has the wrapper character at the beginning and end of the original.

A call to your function should look like this:

print(quote('name', '"'))
"name"

In [ ]:
# write your function here

In [ ]:
# Run this cell after defining your function
print(quote('name', '"'))

Practice 01

If the variable s refers to a string, then s[0] is the string’s first character and s[-1] is its last. Write a function called outer that returns a string made up of just the first and last characters of its input.

A call to your function should look like this:

print(outer('helium'))
hm

In [ ]:
# write your function here

In [ ]:
# Run this cell after defining your function
print(outer('helium'))

Question 01

Explain why the two lines of output appeared in the order they did.

def print_date(year, month, day):
    joined = str(year) + '/' + str(month) + '/' + str(day)
    print(joined)

result = print_date(1871, 3, 19)
print('result of call is:', result)

OUTPUT:

1871/3/19 result of call is: None

COMMIT YOUR WORK

Why Use Functions?

Functions let us break down our programs into smaller bits that can be reused and tested

  • Human beings can only keep a few items in working memory at a time.
  • Understand larger/more complicated ideas by understanding and combining pieces.
    • Components in a machine.
  • Functions serve the same purpose in programs.
    • Encapsulate complexity so that we can treat it as a single “thing”.
  • Also enables re-use.
    • Write one time, use many times.

Testability

Imagine a really big program with lots of lines of code.
There is a problem somewhere in the code because you are not getting the results you expect

How do you find the problem in your code?

If your program is composed of lots of small functions that only do one thing then you can test each function individually.

Reusability

Imagine a really big program with lots of lines of code. There is a section of code you want to use in a different part of the program.

How do you reuse that part of the code?

If you just have one big program then you have to copy and paste that bit of code where you want it to go, but if that bit was a function, you could just use that function

Always keep both of these concepts in mind when writing programs. Try to write small functions that do one thing Your programs should be composed of lots of functions that do one thing Never have one giant function that does a million things.

Our Problem

Last month we ran an experiment in the lab, but one of the windows was left open.

If the temperature in the lab fell below 285 degrees Kelvin all of the data is ruined.

Luckily a data logger was running, but unfortunately it only collects the temperature in fahrenheit.

Example log data:

beginTime,endTime,Temp
1/1/2017 0:00,1/1/2017 1:00,54.0
1/1/2017 1:00,1/1/2017 2:00,11.7
1/1/2017 2:00,1/1/2017 3:00,11.7

Write a function that converts temperatures from Fahrenheit to Kelvin. ((temp_f - 32) * (5/9)) + 273.15)


In [ ]:
def fahr_to_kelvin(temp_f):
    # write your function here
COMMIT YOUR WORK

Documentation

Along the same lines as testability and resusability is documenation.

While python is easy to read and follow, you will either need to share your code with others or you will forget what you did.


In [ ]:
help(round)

Adding documentation to your own code is simple and easy.

Immediately after defining the function add a documenation block with triple-quotes (''')

def add_two_numbers(num1, num2):
    '''
    This is where to put documentation
    Return the sum of two numbers
    '''
    return num1 + num2

Add documentation to your function fahr_to_kelvin.


In [ ]:
# Run this cell after adding documentation
help(fahr_to_kelvin)
COMMIT YOUR WORK

We read the packaging on the materials wrong! If the temperature in the lab fell below -5 degrees Celsius all of the data is ruined.

Write a function that converts temperatures from Kelvin into Celsius. temp_k - 273.15


In [ ]:
# write your function here
COMMIT YOUR WORK

Because we know issues like this happen all of the time, let's prepare for the inevitability.

Write a function to convert fahrenheit to celsius, without a formula.

We could write out the formula, but we don’t need to. Instead, we can compose the two functions we have already created


In [ ]:
# write your function here

This is our first taste of how larger programs are built: we define basic operations, then combine them in ever-large chunks to get the effect we want. Real-life functions will usually be larger than the ones shown here — typically half a dozen to a few dozen lines — but they shouldn’t ever be much longer than that, or the next person who reads it won’t be able to understand what’s going on.

COMMIT YOUR WORK

Write a function to convert from celsius to fahrenheit. (9/5) * temp_c + 32


In [ ]:
# write your function here
COMMIT YOUR WORK

Arguments in call are matched to parameters in definition.

  • Functions are most useful when they can operate on different data.
  • Specify parameters when defining a function.
    • These become variables when the function is executed.
    • Are assigned the arguments in the call (i.e., the values passed to the function).

Default Values

If we usually want a function to work one way, but occasionally need it to do something else, we can allow people to pass a parameter when they need to but provide a default to make the normal case easier.


In [ ]:
def display(a=1, b=2, c=3):
    print('a:', a, 'b:', b, 'c:', c)

print('no parameters:')
display()
print('one parameter:')
display(55)
print('two parameters:')
display(55, 66)

As this example shows, parameters are matched up from left to right, and any that haven’t been given a value explicitly get their default value. We can override this behavior by naming the value as we pass it in:


In [ ]:
print('only setting the value of c')
display(c=77)

In [ ]:
import numpy

In [ ]:
# Why does this not work?
# What is wrong? How to fix it?
numpy.loadtxt('LabTempHourlyJanuary2017.csv', ',')

In [ ]:
help(numpy.loadtxt)

The filename is assigned to fname (which is what we want), but the delimiter string ',' is assigned to dtype rather than delimiter, because dtype is the second parameter in the list. However ‘,’ isn’t a known dtype so our code produced an error message when we tried to run it. When we call loadtxt we don’t have to provide fname= for the filename because it’s the first item in the list, but if we want the ‘,’ to be assigned to the variable delimiter, we do have to provide delimiter= for the second parameter since delimiter is not the second parameter in the list.

It looks like the logger actually can collect celsius after all! Unfortunately it forgets what temperature type to log and has been intermittently logging both.

Example log data:

beginTime,endTime,Temp,TempType
1/1/2017 0:00,1/1/2017 1:00,54.0,F
1/1/2017 1:00,1/1/2017 2:00,11.7,C
1/1/2017 2:00,1/1/2017 3:00,11.7,C

Write a function that either converts to fahrenheit or celsius based on a parameter, with a default assuming fahrenheit ('F')

Remember if/else:


In [ ]:
def convert_temp(temp, temp_type='F'):
    # write your function here

In [ ]:
# Run this cell after writing convert_temp
assert(convert_temp(-40.0, 'F'), -40.0)
assert(convert_temp(0.0, 'C'), 32.0)
assert(convert_temp(32.0, 'F'), 0.0)
assert(convert_temp(54.0), 12.2)
assert(convert_temp(12.2, 'C'), 54.0)
COMMIT YOUR WORK

Let's load the logger data! Use numpy.loadtxt

Don't forget the help function!

What does numpy.loadtxt return?

Write a function that loads a file and loops over each line and converts the temperature to celcius.


In [15]:
# write your code here
COMMIT YOUR WORK

Is the experiment ruined? (If the temperature in the lab fell below -5 degrees Celsius all of the data is ruined.)

Is the experiment ruined according to the first read of material? (If the temperature in the lab fell below 285 degrees Kelvin all of the data is ruined.)


In [ ]: