Subprograms
In Python 3, a subprogram is a named block of code that you write once and can run whenever you need it. You define one using the def keyword, followed by the name you choose, a parameter list in round brackets, and a colon. Everything the subprogram does goes underneath, indented so Python knows it belongs to the definition.
The indented lines are called the body. They do not run when Python reads the def line; they run only when something calls the subprogram by name.
A function is a subprogram whose definition includes a return statement. The return statement does two things at once: it sends a value back to whoever called the function, and it ends the function immediately, so any lines after it in the body are skipped. A procedure is a subprogram with no return statement, so it carries out a task and hands nothing back. If you leave the return out, the subprogram is a procedure, and calling it gives you no value to store or print.
Printing is not returning. A procedure that prints a message has still returned no value, so it is a procedure, not a function.
def showTeam(sport):
print("Your sport is " + sport)
print("Good luck in the match")
def doubleScore(score):
return score * 2
showTeam("hockey")
points = doubleScore(14)
print(points)Output:
Your sport is hockey
Good luck in the match
28
A function is allowed to contain several return statements, but only one of them can run on any particular call. This is handy when you want different results for different inputs: put each return inside a branch, so only the branch that matches is reached.
def describeTemperature(degrees):
if degrees < 5:
return "freezing"
elif degrees < 18:
return "cool"
return "warm"
print(describeTemperature(2))
print(describeTemperature(12))
print(describeTemperature(25))Output:
freezing
cool
warm
Calling the function with 2 stops at the first return, so the lines below it are skipped. Calling it with 25 fails both tests and falls through to the last return. The order of the branches matters: once a return has run, no later one can.
When you call a subprogram, you write its name followed by brackets. Inside the brackets you put the arguments — the actual values you are handing over for this particular call. A subprogram written with two parameters needs two arguments, and the first argument is matched to the first parameter, the second to the second. Swap them round and a function meant to work out price - discount would take the discount off the wrong number.
How you call depends on whether the subprogram is a procedure or a function.
A function hands a value back to the point where it was called, so the call itself counts as a value. That means you can store it in a variable, or drop it straight into an expression or a print():
score = bonus(40, 3) — the returned value is stored in score.total = bonus(40, 3) + bonus(10, 1) — two calls, each used as part of the arithmetic.print(bonus(25, 4)) — the value is passed straight to print().Because a call produces a value, a function can be used wherever a value is expected. The brackets are essential: writing bonus on its own refers to the function without running it, while bonus(40, 3) runs it and gives you the value.
A procedure does a job but sends nothing back, so its call goes on a line as a statement by itself: show_medal('Gold', 3). There is no value to store or to add to a number, so a procedure call cannot be part of an expression. A procedure that uses print() has only displayed text on the screen — that text is not returned to whoever made the call.
def print_score(level, correct):
points = level * correct
print("Level " + str(level) + " scored " + str(points))
def earned_points(level, correct):
return level * correct
print_score(3, 12)
best = earned_points(3, 12)
print(best)
print(earned_points(2, 5) * 10)Output:
Level 3 scored 36
36
100
The call print_score(3, 12) is a statement, while earned_points(3, 12) is used inside a print() because it is a value.
A subprogram is a named block of code that does one job and is called whenever that job is needed. Writing your program this way has real benefits, and they all come from the fact that the code for a task exists in exactly one place.
Without a subprogram you would copy the same lines every time you needed them. A quiz program that works out a percentage after every round might repeat the same five lines for round 1, round 2 and round 3. Put that calculation in a subprogram called percentage() and you call it three times instead. If the formula changes, you edit one place, not three, so there is no chance of the copies drifting apart and producing different answers.
show_score() tells you what happens without you wading through the detail, so the main program reads like a plan.Each of these works because a subprogram has a single clear job, with clear inputs and a clear outcome.
def marks_out_of_ten(score, total):
return round(score / total * 10)
# the same function used for three different tests
print(marks_out_of_ten(18, 20))
print(marks_out_of_ten(7, 10))
print(marks_out_of_ten(45, 50))Output:
9
7
9
A tested subprogram can be dropped into a completely different program, which saves writing and re-testing it. Collections of these are stored in libraries, and once a library is imported you can call its subprograms whenever you need them.
Every variable has a scope: the part of a program where that variable can be seen and used. Where you create a variable decides whether it is local or global.
A variable created inside a subprogram is local to it. It is created when the subprogram is called and thrown away when the subprogram ends, and only the code inside that subprogram can use it. Parameters are local too: each value you pass in is copied into a local variable. Try to use a local variable anywhere else and Python raises a NameError, because the variable no longer exists. This keeps each subprogram self-contained: two subprograms can both use a local variable called count without interfering with each other, and a change in one part of a program cannot silently break another.
A global variable is created in the main program, outside every subprogram. It can be read anywhere in the program, including inside subprograms. However, if you assign to it inside a subprogram, Python creates a new local variable instead — unless you declare it with the global keyword first, which tells Python you mean the one in the main program.
lives = 3 # global variable, created in the main program
def lose_life():
global lives # use the global variable, not a new local one
lives = lives - 1
lose_life()
print("Lives left: " + str(lives))Output:
Lives left: 2If a local variable has the same name as a global variable, they are completely separate variables held in separate places. Changing the local one does not change the global one, and the global value is still there once the subprogram has finished.
points = 50 # global variable
def bonus_round():
points = 200 # local variable with the same name
print("Inside the subprogram: " + str(points))
bonus_round()
print("Back in the main program: " + str(points))Output:
Inside the subprogram: 200
Back in the main program: 50