Class 9: Functions
A painful analogy
What do you do when you wake up in the morning?
I don’t know about you, but I get ready.
“Obviously,” you say, a little too snidely for my liking. You’re particular, very detail-oriented, and need more information out of me.
Fine, then. Since you’re going to be nitpicky, I might be able to break it down a little bit more for you…
- I get out of bed
- I take a shower
- I get dressed
- I eat breakfast
Unfortunately that’s not good enough for you. “But how do you eat breakfast?” Well, maybe I…
- Get a bowl out of a cabinet
- Get some cereal out of the pantry
- Get some milk out of the fridge
- Pour some cereal into a bowl
- Pour some milk into the bowl
- Sit down at the table and start eating
“Are you eating with a spoon?” you interrupt. “When did you get the spoon out? Was that after the milk, or before the bowl?”
It’s annoying people like this that make us have functions.
FUN FACT: The joke’s on you, because I don’t even actually eat cereal. Maybe I don’t even get ready in the morning, either.
What is a function?
Functions are chunks of code that do something. They’re different than the code we’ve written so far because they have names.
Instead of detailing each and every step involved in eating breakfast, I just
use “I eat breakfast” as a shorthand for many, many detailed steps. Functions
are the same - they allow us to take complicated parts of code, give it a name,
and type just_eat_breakfast()
every morning instead of twenty-five lines
of code.
What are some examples of functions?
We’ve used a lot of functions in our time with Python. You remember our good
buddy len
? It’s a function that gives back the length of whatever you send
its way, e.g. len("ghost")
is 5
and len("cartography")
is 11.
Almost everything useful is a function. Python has a ton of other built-in functions!
Along with len
, a couple you might have seen are:
abs(...)
takes a number and returns the absolute value of the numberint(...)
takes a string or float and returns it as an integerround(...)
takes a float and returns a rounded version of itsum(...)
takes a list and returns the sum of all of its elementsmax(...)
takes a list and returns the largest of all of its selementsprint(...)
takes whatever you want to give it and displays it on the screen
Functions can also come from packages and libraries. The .get
part of
requests.get
is a function, too!
And here, to prove it to you?
See? Functions make the world run.
One useful role they play is functions hide code that you wouldn’t want to
type a thousand times. For example, you might have used urlretrieve
from
urllib
to download files from around the internet. If you didn’t use
urlretrieve
you’d have to type all of this:
Horrifying, right? Thank goodness for functions.
Writing your own functions
I’ve always been kind of jealous of len(...)
and its crowd. It seemed unfair
that Python made a list of cool, important functions, and neither me nor you had
any say in the matter. What if I want a function that turns all of the periods
in a sentence into exclamation points, or prints out a word a hundred million
times?
Well, turns out that isn’t a problem. We can do that. Easily! And we will.
If you can type def
and use a colon, you can write a function.
A function that you write yourself looks like this:
It has a handful of parts:
def
- tells Python “hey buddy, we’re about to define a function! Get ready.” And Python appropriately prepares itself.double
- is the name of the function, and it’s how you’ll refer to the function later on. For example,len
’s function name is (obviously)len
.(number)
- defines the parameters that the function “takes.” You can see that this function is calleddouble
, and you send it one parameter that will be callednumber
.return bigger
- is called the return statement. If the function is a factory, this is the shipping department - return tells you what to send back to the main program.
You’ll see it doesn’t do anything, though. That’s because we haven’t called the function, which is a programmer’s way of saying use the function. Let’s use it!
Function Naming
Your function name has to be unique, otherwise Python will get confused. No other functions or variabels can share its name!
For example, if you call it len
it’ll forget about the built-in len
function, and if you give one of your variables the name print
suddenly Python
won’t understand how print(...)
works anymore.
If you end up doing this, you’ll get errors like the one below
Parameters
In our function double
, we have a parameter called number
.
def double(number):
bigger = number * 2
return bigger
Notice in the last example up above, though, we called double(age)
. Those
don’t match!!!
The thing is, your function doesn’t care what the variable you send it is called. Whatever you send it, it will rename. It’s like if someone adopted my cat Smushface, they might think calling her Petunia would be a little bit nicer (it wouldn’t be, but I wouldn’t do anything about it).
Here’s an example with my favorite variable name potato_soup
invitation
and line
both get renamed to potato_soup
inside of the
function, so you can reuse the function with any variable of any name.
Let’s say I have a function that does some intense calculations:
def sum_times_two(a, b):
added = a + b
return added * 2
To reiterate: a
and b
have nothing to do with the values outside of the
function. You don’t have to make variables called a
and b
and then send
them to the function, the function takes care of that by itself. For example,
the below examples are perfectly fine.
sum_times_two(2, 3)
r = 4
y = 7
sum_times_two(r, y)
When you’re outside of the function, you almost never have to think about
what’s inside the function. You don’t care about what variabels are called or
anything. It’s a magic box. Think about how you don’t know what len
looks
like inside, or print
, but you use them all of the time!
Why functions?
Two reasons to use functions, since maybe you’ll ask:
Don’t Repeat Yourself - If you find yourself writing the same code again and
again, it’s a good time to put that code into a function. len(...)
is a
function because Python people decided that you shouldn’t have to write length-
calculating code every time you wanted to see how many characters were in a
string.
Code Modularity - sometimes it’s just nice to organize your code. All of your parts that deal with counting dog names can go over here, and all of the stuff that has to do with boroughs goes over there. In the end it can make for more readable and maintanable code. (Maintainable code = code you can edit in the future without thinking real hard)
Those reasons probably don’t mean much to you right now, and I sure don’t blame you. Abstract programming concepts are just dumb abstract things until you actually start using them.
Let’s say I wanted to greet someone and then tell them how long their name is, because I’m pedantic.
Do you know how exhausted I got typing all of that out? And how it makes no sense at all? Luckily, functions save us: all of our code goes into one place so we don’t have to repeat ourselves, and we can give it a descriptive name.
return
The role of a function is generally to do something and then send the result
back to us. len
sends us back the length of the string, requests.get
sends
us back the web page we requested.
def double(a):
return a * 2
This is called the return
statement. You don’t have to send something
back (print
doesn’t) but you usually want to.
Writing a custom function
Let’s say we have some code that compares the number of boats you have to the number of cars you have.
if boat_count > car_count:
print "Larger"
else:
print "Smaller"
Simple, right? But unfortunately we’re at a rich people convention where they’re always comparing the number of boats to the number of cars to the number of planes etc etc etc. If we have to check again and again and again and again for all of those people and always print Larger or Smaller I’m sure we’d get bored of typing all that. So let’s convert it to a function!
Let’s give our function a name of size_comparison
. Remember: We can name
our functions whatever we want, as long as it’s unique.
Our function will take two parameters. they’re boat_coat
and car_count
above, but we want generic, re-usable names, so maybe like, uh, a
and b
?
For our function’s return value, let’s have it send back "Larger"
or
"Smaller"
.
Your Turn
This is a do-now even though it’s not the beginning of class!
1a. Driving Speed
With the code below, it tells you how fast you’re driving. I figure that a lot of people are more familiar with kilometers an hour, though, so let’s write a function that does the conversion. I wrote a skeleton, now you can fill in the conversion.
Make it display a whole number.
1b. Driving Speed Part II
Now write a function called to_mpm
that, when given miles per hour, computes
the meters per minute.
1c. Driving Speed Part III
Rewrite to_mpm
to use the to_kmh
function. D.R.Y.!
2. Broken Function
The code below won’t work. Why not?
3. Data converter
We have a bunch of data in different formats, and we need to normalize it! The data looks like this:
var first = { 'measurement': 3.4, 'scale': 'kilometer' }
var second = { 'measurement': 9.1, 'scale': 'mile' }
var third = { 'measurement': 2.0, 'scale': 'meter' }
var fourth = { 'measurement': 9.0, 'scale': 'inches' }
Write a function called to_meters(...)
. When you send it a dictionary, have it
examine the measurement
and scale
and return the adjusted value. For the
values above, 3.4 kilometers should be 3400.0 meters, 9.1 miles should be around
14600, and 9 inches should be apprxoimately 0.23.