Python (and most languages) have a way to wrap code up so it can be called repeatedly: functions.
A function is a piece of code with a name. Other code calls the function when it wants something done.
Let's take the name tag program we wrote at the beginning of the course.
- first_name = input('What is your first name? ')
- last_name = input('What is your last name? ')
- full_name = first_name + ' ' + last_name
- print('Hello!')
- print('My name is')
- print(full_name)

Ray
Man, that code looks so easy now.
Aye. Difficulty is a relative thing, not absolute.
Let's say we have a list of people we want name tags for. We could write this:
- first_name = 'Wednesday'
- last_name = 'Addams'
- full_name = first_name + ' ' + last_name
- print('Hello!')
- print('My name is')
- print(full_name)
- first_name = 'Xavier'
- last_name = 'Thorpe'
- full_name = first_name + ' ' + last_name
- print('Hello!')
- print('My name is')
- print(full_name)
- first_name = 'Tyler'
- last_name = 'Galpin'
- full_name = first_name + ' ' + last_name
- print('Hello!')
- print('My name is')
- print(full_name)
- first_name = 'Enid'
- last_name = 'Sinclair'
- full_name = first_name + ' ' + last_name
- print('Hello!')
- print('My name is')
- print(full_name)
(I love that show.)
Repeat for as many people we have.
A better way
Can we avoid having so much repeated code? Check this out:
- def make_name_tag(first_name, last_name):
- full_name = first_name + ' ' + last_name
- print('Hello!')
- print('My name is')
- print(full_name)
- make_name_tag('Wednesday', 'Addams')
- make_name_tag('Xavier', 'Thorpe')
- make_name_tag('Tyler', 'Galpin')
- make_name_tag('Enid', 'Sinclair')
Lines 1 to 5 make a function called make_name_tag
. (def
stands for "define.") We've taken out the repeated code, and made it into it's own little chunk.

Ethan
That's so much less code.
Yes, it is. From 27 lines to 10. Less code means faster to write, easier to debug, and faster to change. Cost control!
These things...
- def make_name_tag(first_name, last_name):
... are called parameters or arguments. They're like placeholders. Whatever value you put into them goes into those slots in the code.
Python doesn't care what the parameters are called. It just matches up their names with places in the code.
Any of these would work:
- def make_name_tag(first_name, last_name):
- full_name = first_name + ' ' + last_name
- print('Hello!')
- print('My name is')
- print(full_name)
- def make_name_tag(name_first, name_last):
- full_name = name_first + ' ' + name_last
- print('Hello!')
- print('My name is')
- print(full_name)
- def make_name_tag(thing1, thing2):
- full_name = thing1 + ' ' + thing2
- print('Hello!')
- print('My name is')
- print(full_name)
- def make_name_tag(something, something_else):
- full_name = something + ' ' + something_else
- print('Hello!')
- print('My name is')
- print(full_name)
Which one of the four do you like best?

Adela
The first one. The parameters' names tell you what they mean.
Aye, that's so. Best to use meaningful names everywhere. That includes the names of functions, as well as parameters.
Bee tee dubs, a function can have any number of params, from zero on up.

Ethan
Could you do this?
- def make_name_tag(first_name, last_name):
- full_name = first_name + ' ' + last_name
- print('Hello!')
- print('My name is')
- print(full_name)
- given_name = 'Wednesday'
- family_name = 'Addams'
- make_name_tag(given_name, family_name)
Would that work?

Georgina
I'm guessing it would, since the parameter names can be anything.

Ray
Wait. Wouldn't you need to change the parameters names? To:
def make_name_tag(given_name, family_name):
It might seem like that, but Georgina's right. def
doesn't care what the parameters are called.

Ray
OK, but how does it know which name is the first?
Python uses the position of the parameters. The first parameter in the call matches the first param in the def
, the second param in the call matches the second in the def
, and so on.

Georgina
Wait, doesn't that mean you could mix things up accidentally? Like this:
- def make_name_tag(first_name, last_name):
- full_name = first_name + ' ' + last_name
- print('Hello!')
- print('My name is')
- print(full_name)
- family_name = 'Addams'
- given_name = 'Wednesday'
- # Wrong order!!
- make_name_tag(family_name, given_name)
What would this code output?

Ethan
You'd get:
- Hello!
- My name is
- Addams Wednesday
That's right. It's a fairly common bug to get parameters in the wrong order.
An even better way
Actually, I'd write the program like this:
💩Smelly old function💩 | ✨Sparkling new lemon-fresh function✨ |
---|---|
|
|
The new function doesn't print
directly. Instead, it assembles the output into a string, and returns it to the caller. That's what the return
statement does: send a value to whatever code called the function.

Ethan
What's the \n
thing?
Remember, a string can contain any character you can type. When you hit Enter, you're typing a character that means "go to the next line." Most languages use \n
to show Enter in a string.

Georgina
So... would this code make the Dr. Seuss thing?
- rhyme = 'One fish\nTwo fish\nRed fish\nBlue fish\n'
- print(rhyme)
Aye! It would. You can put them ol' \n
s in the middle of a string, though I don't usually. I prefer to keep the code looking like the output:
- rhyme = 'One fish\n'
- rhyme += 'Two fish\n'
- rhyme += 'Red fish\n'
- rhyme += 'Blue fish\n'
- print(rhyme)
There are other ways to do the multiline-string spell. You can google it.

Ray
OK, but you haven't told us why you like the lemon-fresh approach.
Oh, right! Here's the code again.
💩Smelly old function💩 | ✨Sparkling new lemon-fresh function✨ |
---|---|
|
|
The smelly version of make_name_tag
always shows the output in the console. The print
s are in the function. If you want to change where the output goes, you change the function. It's best to write functions that don't need to change much.
The sparkly new version returns a string to the main program. You can do anything with the string, like put it in a variable, print it, whatevs.
Here's a version that accumulates all the output into the variable tags
, and sends it to a network printer:
- def make_name_tag(first_name, last_name):
- tag_text = 'Hello!\n'
- tag_text += 'My name is\n'
- tag_text += first_name + ' ' + last_name + '\n'
- return tag_text
- # Accumulate name tags.
- tags = make_name_tag('Wednesday', 'Addams')
- tags += make_name_tag('Xavier', 'Thorpe')
- tags += make_name_tag('Tyler', 'Galpin')
- tags += make_name_tag('Enid', 'Sinclair')
- send_to_network_printer('printer3', tags)
The function make_name_tag
hasn't changed from the print-to-console version.
I made up send_to_network_printer
for this example. It doesn't exist.
This next one accumulates the output and writes it to a file, so you can edit it with Writer or Word, email it to someone, whatevs.
- def make_name_tag(first_name, last_name):
- tag_text = 'Hello!\n'
- tag_text += 'My name is\n'
- tag_text += first_name + ' ' + last_name + '\n'
- return tag_text
- # Accumulate name tags.
- tags = make_name_tag('Wednesday', 'Addams')
- tags += make_name_tag('Xavier', 'Thorpe')
- tags += make_name_tag('Tyler', 'Galpin')
- tags += make_name_tag('Enid', 'Sinclair')
- # Writing to file
- with open('./name tags.txt', 'w') as name_tags_file:
- # Writing data to a file
- name_tags_file.write(tags)
This one does work. We'll talk more about files later.
Again, make_name_tag
hasn't changed from the print-to-console version.

Georgina
That's so cool!
You can use the same function to make the name tag data, but then do whatever with it.
Aye, it has excessive cools. You can reuse the function any way you want.
Changey changey
Here's our code again, the network printer version.
- def make_name_tag(first_name, last_name):
- tag_text = 'Hello!\n'
- tag_text += 'My name is\n'
- tag_text += first_name + ' ' + last_name + '\n'
- return tag_text
- # Accumulate name tags.
- tags = make_name_tag('Wednesday', 'Addams')
- tags += make_name_tag('Xavier', 'Thorpe')
- tags += make_name_tag('Tyler', 'Galpin')
- tags += make_name_tag('Enid', 'Sinclair')
- send_to_network_printer('printer3', tags)
Let's say we want to say G'day instead of Hello, for all the name tags.
How would you change the code?

Adela
Just change line 2 from print('Hello!')
to print("G'day")
.
Right. This works because the same function, make_name_tag
, makes all the tags. Change it, and all the tags change.
Functions make teams work
Complex programs aren't written by one person, usually. Different people work on different parts of the same program at the same time.

Ethan
How does that work? If all four of us worked on a program, how would we know what variables names to use, prompts, like that?
The key is coordinating ahead of time. You set things up so different people work on different pieces of code, and it works when you put it all together.
You saw one coordination mechanism early in the course.
What coordination mechanism have you seen?
(Crickets)

Adela
Oh! Is it those structure diagrams?
Aye! Here's one Adela made:
Structure diagram

Ethan
How does that help?

Adela
Ooo! I get it! The input code needs to make the variables small_goats
, medium_goats
, large_goats
, and months
. We could give that Georgina, and she could write the code, since she knows what it needs to send to the next step.
Ethan could write the processing code at the same time as Georgina is doing her work. He knows what Georgina's code will give, and what the next chunk, output, needs.
Aye! Good thinking, Adela.
Functions give you even better coordination. You could tell someone (let's call her Elle Cordova (I'm a fan)):
"Write a function called make_name_tag
that takes two string parameters: first name, and last name, in that order. The function returns the text of a name tag."
You don't have to tell Elle where first and last name come from. The function won't care. You don't have to give the parameter names, like first_name
. It doesn't matter, since params values are matched up by position. These are fine:
- def make_name_tag(first_name, last_name):
- def make_name_tag(given_name, family_name):
The first parameter is the first name, and the second is the last name, no matter what Elle names them.
This wouldn't be OK:
- def make_name_tag(last_name, first_name):
It doesn't match the specifications (specs) we gave Elle: "takes two string parameters: first name, and last name, in that order."
Let's leave things here for now. We'll talk more about cool function stuff later.
Summary
- A function is a piece of code with a name.
- Other code calls the function when it wants something done.
- Send data into functions with parameters, also called arguments. They're like placeholders. Functions can have any number of parameters, including none.
- Python uses the position of parameters to work out what goes where.
- Functions can send data back to callers with the
return
statement. \n
in a string means, "Press the Enter key here."- Change something in a function, and it will apply every time the function is called.
- Functions help coordinate teams.