Writing functions
def, calling, and why subprograms help.
Do this lesson in the simulatorYou have been calling functions since lesson F1.3: print, forward, distance. Now you write your own. A function is a named block of code you can run whenever you like, as often as you like, by calling its name. Exams call it a subprogram.
Defining a function
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
def report():
x, y = position()
print(f"at x={x} y={y}, wall in {distance()} cm")
report()
forward(60, distance=20)
report()
def report(): defines a function called report. The indented block is its body, and nothing in it runs yet. Defining is like writing a recipe: nothing is cooked. report() calls it, and only then does the body run. Here it is called twice, so the report prints twice, and you wrote it once.
Define first, then call
Python reads a program top to bottom, so a function must be defined before the line that calls it runs:
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
signal()
def signal():
led("red")
tone(880, 0.2)
led("off")
NameError: name 'signal' is not defined. Move the call below the def and run again. This is why programs usually put all their functions near the top, and the main steps underneath.
What happens when a function is called
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
def signal():
print(" signal starts")
led("red")
tone(880, 0.2)
led("off")
print(" signal ends")
print("before")
signal()
print("between")
signal()
print("after")
Watch the order of the lines in the console. At each call, the program jumps into the function, runs its body, then comes back to the line after the call. Press Debug and step through it to see the jumps happen line by line.
A function can call other functions
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
def signal():
led("red")
tone(880, 0.2)
led("off")
def side():
forward(60, distance=20)
signal()
turn_right(30, angle=90)
side()
side()
side()
side()
side uses signal, and the main program uses side. Each function is small and does one job, and the four side() calls read almost like English: drive a square, signalling at each corner.
Why write functions?
- No repetition. The signal is written once. Change it once and every corner changes.
- Names explain.
side()says what four lines do. - Small pieces are easier to test. You can run
signal()on its own until it is right, then build on it. - Teams can split the work. One person writes
signal, another writesside, as long as they agree what each one does.
Task: signal at the corners
Write a function signal() that turns the LED red, plays a short note, and turns the LED off. Then drive a square of 25 cm sides, calling signal() at every corner. Call your function; do not repeat its lines.
# the two lines every program starts with: the commands, then the robot
from bugbot import *
connect()
def signal():
led("red")
forward(60, distance=25)
turn_right(30, angle=90)
Challenges
- Write
siren()that alternates two notes four times, and call it at the start and the end of a drive. - Put the four
side()calls inside a functionsquare(), and callsquare()twice. - What happens if you call a function inside itself? Try it with a function that only prints, and read the error.