What a Function Is
A function is a piece of code with a name attached to it. You write the code once, under that name. Then, wherever you need it, you write the name — and the code stored under it runs. That is the whole idea, and everything else in this chapter is detail.
A function is a named block of code that performs a specific, well-defined task. It is written once and can be reused any number of times by referring to its name.
The name is the identifier associated with that block. When the name is used — with brackets after it — the block of code stored under that name is executed. Functions are what make a program modular: a long program is divided into smaller, manageable, logical units, each doing one job.
1The problem functions solve
Here is a bill. The line of dashes is printed four times, and each time it is typed out again in full:
# the same line, typed out four times
print('-' * 40)
print('BILL')
print('-' * 40)
print('Pens 3 x 10 = 30')
print('-' * 40)
print('TOTAL 30')
print('-' * 40)---------------------------------------- BILL ---------------------------------------- Pens 3 x 10 = 30 ---------------------------------------- TOTAL 30 ----------------------------------------
It works. But if the shop decides the bill should be 50 characters wide instead of 40, you have four lines to find and change — and this is a four-line bill. On a real one you would have twenty, and you would miss one.
2Give the code a name
# the line is written once, under the name 'line'
def line():
print('-' * 40)
line()
print('BILL')
line()
print('Pens 3 x 10 = 30')
line()
print('TOTAL 30')
line()---------------------------------------- BILL ---------------------------------------- Pens 3 x 10 = 30 ---------------------------------------- TOTAL 30 ----------------------------------------
Identical output. The difference is that the instruction print('-' * 40) now exists in one place. Change the 40 to a 50 there, and every line in the bill changes with it.
Look closely at the two lines that make the function. They are not the same kind of line, and each has a name:
The header is the def line. It supplies the name (identifier) the block will be stored under, and it ends in a colon. The colon is a promise that an indented block follows.
The body is everything indented under that header. This is the actual code — the work the function does. Indentation is what marks it out: the first line back at the left margin is no longer part of the function.
So the header names a block, and the body is the block. That is the whole shape of a function, and it is the same shape you already know from if and for — a line ending in a colon, then an indented block belonging to it. A function body can hold as many lines as the job needs, and every one of them must be indented by the same amount.
# four lines in the body, all indented under the header
def banner():
print('-' * 30)
print('LAMBDALAB')
print('-' * 30)
print('Welcome')
banner()
print('back at the margin, outside the function')------------------------------ LAMBDALAB ------------------------------ Welcome back at the margin, outside the function
The last print starts at the left margin, so it is not in the body — it belongs to the main program and runs after the function has finished.
def line():
print('-' * 40)Storing the code under a name. Nothing is printed. Nothing runs.
line()Writing the name, with brackets. Now the stored code runs.
3The name is doing the work
Read the call again: line(). Python looks up the name line, finds the code you stored under it, and runs that code. Then it comes back and carries on with the next line of your program. Every call does the same thing.
# one definition, three calls
def greet():
print('Good morning, class!')
greet()
greet()
greet()Good morning, class! Good morning, class! Good morning, class!
greet without () — is just a mention of the function, the way marks is a mention of a list. Python looks it up, finds a function, and does nothing with it:def greet():
print('Good morning, class!')
print('before')
greet # a mention, not a call — nothing happens
print('after')before after
4Invocation: the call is what activates it
Writing a function and running it are two separate events, and the second one has a name. Using a function — writing its name with brackets — is called invoking it, or calling it. The two words mean exactly the same thing, and both turn up in exam questions.
A function call (or function invocation) is the statement that activates a function — it transfers control to the block of code stored under that name and executes it.
A function definition merely stores the code under a name. It does not activate it. Until the function is invoked, not one line of its body is ever executed.
The proof is a program that defines a function perfectly well and never invokes it:
def line():
print('-' * 40) # this line is never executed
print('program started')
print('program finished')program started program finished
Not a single dash. The definition ran — the name line now exists and the code is stored under it — but without an invocation the body simply sits there.
def line():
print('-' * 40)Written once. Creates the name. Runs nothing. Happens whether you ever use the function or not.
line()Written as often as you like. Transfers control into the body, runs it, and comes back. This is the event that produces output.
5Modularity: one big program, many small pieces
The bill example saves you some typing. The real reason functions matter is bigger than that, and it has a name: modularity.
Compare the two ways of describing the same billing program:
300 lines, top to bottom. To find the bit that works out GST you read until you recognise it. To fix a rounding bug you hope it only happens in one place. Two people cannot work on it at once.
print_header()
items = read_items()
total = compute_total(items)
gst = compute_gst(total)
print_footer(total, gst)Five lines that say what the program does. The GST bug is in compute_gst, and nowhere else.
That right-hand version is the point of this chapter. Each of those names is a function; each holds a handful of lines; and the main program becomes short enough to read in one go.
6What you get from a function
Write it once, call it as often as you like — three times or three hundred, from anywhere in the program.
One long program becomes a set of small units, each doing one job, each with a name that says what it is.
A bug in the code lives in exactly one function. Correct it there and every call is corrected.
compute_gst(total) says what is happening. The eleven lines that do it are somewhere else, and you can read them when you care.
7Recap
def stores the code under the name. Nothing runs at that moment.
Calling — or invoking — transfers control into the body. A function that is defined but never invoked runs nothing at all.
greet is a mention and does nothing. greet() is a call and runs the function.
The program becomes a set of small named units instead of one long list of instructions.
- 1
Write a function
stars()that prints a row of 20 asterisks, and call it three times.Hint ·
def stars():withprint('*' * 20)indented under it. - 2
Write a function that prints your school's name and address, and use it at the top of two different bills.
Hint · Several
print()lines in one function. Change the address once and both bills change. - 3
Take a program you wrote in Class 11 and name three jobs inside it that could each become a function.
Hint · Look for anything you could describe in three words — “read the marks”, “work out the average”, “print the report”.
What does def line(): actually do when the program reaches it?
What does the program print if you write greet without the brackets?
A program defines a function and never calls it. What runs?
What does modularity mean?