In this lab, we will learn how to create and call functions. Functions are blocks of code that are reusable throughout a program. You’ve already encountered functions such as
print(), which is a function built into Python.
What is a function?
Before we can talk about functions, we need to talk about code blocks. A code block is one or more lines of code. Here’s one:
Sometimes we want to talk about how many times a code block should run, or whether it should run at all. Consider this code, which will draw a triangle:
We have the same code block, but now it’s indented under the loop on line 1. This means the code block should run once for each item in the range. A few things to note:
- Whenever a code block is indented, there’s always a line introducing it. This line always ends with a colon.
- The way you indent matters. Always use the tab key to indent.
- When you’re done with a code block, just stop indenting.
Often times we want to reuse a code block in different sections of a program.
Functions let you give a name to a code block so you
can reuse it without having to copy and paste.
A few things to note:
- The structure of the function definition looks a lot like a for-loop. The introduction on line 1 ends with a colon, just like the for-loop on line 2.
defkeyword (line 1) tells the computer you’re defining a new function.
- The function’s name,
draw_triangle, comes right after
- After the function’s name is the list of arguments, surrounded by parentheses
(side_length). Arguments are the things you need to tell the program before you can use the function. Think of arguments as questions the program might ask about what to do. For
draw_triangle, the program wants to know “How long should the length of the sides be?” and you have to tell it the
side_length. When a function doesn’t need any arguments, its argument list will look like
- In the function’s code block, you can use the arguments as variables. The value of the argument will be assigned when the function is called. You could draw a small triangle by running
draw_triangle(10)and a big triangle by running
👾 💬 Functions make your code simpler.
Instead of writing all the code for a triangle over and over, you can get it right once and put it in a function. Once you have written a function, you must call it. Calling a function tells Python to run that block of code. Just as you can’t read the value of a variable before it has been defined, you can’t call a function before it has been defined.
Look at the code below. Answer the questions in your notebook before moving on:
- What argument does the
- How is that argument used in the
- On which line is the
- On which line is the
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
def hexagon(side_length): "Draws a hexagon." for i in range(6): forward(side_length) right(360 / 6) def draw_honeycomb(): "Draws a honeycomb pattern of seven hexagons." for each_side in range(6): pendown() hexagon(20) penup() forward(20) left(360 / 6) draw_honeycomb()
This program will draw the pattern below.
When you want to draw something fancy, you need to break it down into smaller steps. Then you can write functions to do the smaller steps, and write more functions to combine small steps into bigger steps. This concept is called decomposition. (Going the other direction, the process of combining simple behaviors into more complex behaviors is called composition.)
Let’s decompose the complex drawing of an ice cream cone into simple parts:
- To draw an ice cream cone with
- Draw the cone:
- Do this
- Move the turtle up.
- Draw a scoop of ice cream.
~/Desktop/making_with_code/unit00/lab06/ice_cream_cone.py and read the code.
How might these functions work together?
👾 💬 Docstrings
Did you notice how the first line of each function is a string describing the function? These are called docstrings and they don’t have any effect on how your code runs. Docstrings are mostly meant to help programmers understand what the function is for, but there are some fancy Python programs which read other Python programs and automatically extract docstrings to create a description of the program.
💻 Replace the comment on line 21 with code
draw_ice_cream_cone function. Use
draw_ice_cream_scoop as if they
were already working–we’ll take care of them next. Let’s elaborate the pseudocode we wrote above, bringing it a bit closer to Python:
50(This controls how much higher each scoop should be.)
scoop_count * scoop_offset
Once you finish translating this pseudocode,
draw_ice_cream_cone still won’t do anything because it
draw_ice_cream_scoop to do the actual drawing, and these functions don’t do anything yet. Implement them now. Even if the cone and the scoops don’t look great at first, you will see
the general pattern of the ice cream cone taking shape: one cone and three scoops.
👾 💬 How to fill a shape with color
To fill your turtle drawing with color, use the
end_fill()functions as shown below. This chart lists recognized color names.
def draw_triangle(sideLength): #This function draws a triangle for i in range(3): left(120) forward(sideLength) fillcolor("Blue") begin_fill() #Tells the turtle to start the color fill draw_triangle(20) end_fill() #Tells the turtle to stop the color fill
Design your own functions
In this exercise you will need to write some functions on your own. Our aim is to create a grid of squares.
grid.py and read the code.
👾 💬 Triple quotes
When you need a string to be longer than one line (as in the verbose docstring on lines 12-14), use triple-quotes. Everything between pairs of triple-quotes is contained within a single string.
grid_of_squares function looks like a lot of work. We will need to decompose this problem
into simpler subproblems. Here is one way you could do it:
- To draw a grid of squares, we need to draw a bunch of rows of squares, each at a certain
- To draw a row of squares, we need to draw a bunch of squares, each at a certain
- To draw a square, we need to draw four sides of the correct length.
If you use this decomposition strategy, you’ll need to write several new functions:
row_of_squares(side_length, margin, number_of_squares)
Think about the arguments for each of these functions. Why does each function need to know this information?
Add the functions
row_of_squares(side_length, margin, number_of_squares) and
to your program and implement them. Now that you have decomposed the problem, it might be a good idea to
compose the solution, starting from the simplest pieces. Make sure your
square function works,
then see if you can get
row_of_squares to write
Ice cream parlor
Let’s return to
Right now, both the color of the ice cream and the number of scoops are pre-determined or hard-coded. If you wanted to change the color or number of scoops, you would have to go back into the code and change it yourself.
💻 Expand the functionality of this program to simulate an ice cream parlor. The user should be able to choose the flavor of the ice-cream and the number of scoops.
👾 💬 Hints
Consider the following:
- How will you implement the functionality of a
flavorthat is not hard-coded?
- How will you include user input?
- How will you translate the flavor “chocolate” to the color “brown?
Here is an example interaction:
python3 ice_cream.py --- Welcome to the ice cream parlor --- What flavor would you like? > Select a flavor (chocolate, strawberry, vanilla): chocolate How many scoops would you like? > Select number of scoops (max 3): 3 --- Enjoy your ice cream! Please come again! --- [Press any key to exit]
Let’s return to
💻 Expand the functionality of this program so the user can customize the size and colors in the grid. For example:
$ python3 grid.py --- PATERN GENERATOR --- How many rows? > Enter a number: 5 How many columns? > Enter a number: 3 Pick a primary color. > Choose a color (darkseagreen, coral, deeppink): darkseagreen Pick a secondary color. > Choose a color (darkred, , cyan, cadetblue): coral [Press any key to exit]