This is the last of the Turtle Graphics readings. It will teach you how to define your own commands, or functions.
When you create your own command or function, you are capturing pieces of your program for later use. When you do this, you avoid having to write the same code multiple times. Instead, each time you want Python to execute a particular sequence, you simply invoke the name of the function you created. Python will then refer to a place in your program where you wrote that sequence.
Functions, like for loops, help you to follow the principle "don't repeat yourself" (DRY).
If you'd like to follow along, open the following URL in a separate tab or window:
https://repl.it/languages/python_turtle
I would recommend making an account on REPL if you haven't already, so you can save your code and revisit it later.
In the last reading, you saw how a for loop can be used to reduce the length and redundancy of code. In order for a for loop to be effective, the repetitive portion of a program must occur back-to-back-to-back, like this:
forward(50)
backward(50)
left(90)
forward(50)
backward(50)
left(90)
forward(50)
backward(50)
left(90)
forward(50)
backward(50)
left(90)
Now, suppose you have a piece of code that happens more than once in a program, but those occurrences are not next to each other. Say, for example, that you are writing a program, and you occasionally want to draw a small square, like this:
Perhaps the larger picture you are trying to draw might look something like this:
Since the squares in this drawing aren't made immediately after one another, we cannot simply use a for loop to repeat the segment of code that draws a single square. What we can do instead is create a command that draws a square and invoke that command each time we need a square drawn.
The technical term for a command in Python is a function. Every time you've used forward and backward, for example, you've actually been using functions called forward and backward. Invoking a function by using its name in your program is known as calling the function.
When you call the forward function, for example, there are a number of things Python must do to respond to this function call: it must compute the arrow's new location based on the distance (provided in parentheses) and the arrow's current direction, make note of the fact that there may be a new line segment on the screen, and update the result window to display everything that has happened. The code that makes all this happen is hidden from you, but take on faith that some amount of code must be executed in order for all this to happen. Instead of making you write that code every time you want to move forward, Python keeps it all locked in a function called forward. Whenever you call the forward function, Python knows to go and execute the other code needed to make the arrow move forward. In this way, a function can be thought of as an alias for another section of code.
The main concepts in this module will become more clear when you start making your own functions. Let's start with a simple example: say we want to make a new function called forward_backward_twenty
. As the name suggests, calling this function will cause the arrow to move forward 20 and then backward 20.
We can create the function like this:
from turtle import *
def forward_backward_twenty():
forward(20)
backward(20)
The first unfamiliar part of this is syntax is the word def
. It is short for define, and it indicates that you are about to define a new function. Function definitions in Python always start with def
. def
is then immediately followed by the function name, a pair of parentheses, and a colon. (Later, we will learn when it is appropriate to put things in the parentheses.)
Everything after the definition line that has been indented is considered to be in the function (or part of the function body). In this way, a function definition is similar to a for loop. Like with a for loop, with a function definition, the indentation must be uniform. Anything that is not indented is treated as outside the function body.
Note that the program above doesn't actually do anything; that is, it doesn't have any effect on the arrow. By defining the function, we are merely teaching Python what forward_backward_twenty
means. We are not actually asking Python to execute forward_backward_twenty
. In more technical terms, we are defining the new function, but we have yet to call that function.
Let's add some function calls to the program:
from turtle import *
def forward_backward_twenty():
forward(20)
backward(20)
forward_backward_twenty()
left(90)
forward_backward_twenty()
The last three lines of the program above actually cause the arrow to do something. Once forward_backward_twenty
has been defined, it can be used just like any other command.
If we did not have the ability to define functions in Python, the above program would have to be written like this:
from turtle import *
forward(20)
backward(20)
left(90)
forward(20)
backward(20)
Notice the two identical segments of code. Since they are not adjacent, we cannot use a for loop to condense the program. By creating a function that contains the two repeated lines, we only have to write the two-line sequence once, and it can be re-used whenever we need the arrow to move forwards and backwards by 20.
Here is a program that makes a function called draw_square
and uses it to make the picture shown at the beginning of this reading:
from turtle import * def draw_square(): forward(20) left(90) forward(20) left(90) forward(20) left(90) forward(20) left(90) draw_square() forward(50) right(90) forward(100) draw_square() left(90) forward(20) draw_square() left(90) forward(20) draw_square()
This program can actually be condensed even further. Notice the repetition in the code within the function:
def draw_square(): forward(20) left(90) forward(20) left(90) forward(20) left(90) forward(20) left(90)
We can actually turn this into a for loop! Since this for loop is inside the body of a function, the body of the for loop will have to be indented by two levels:
def draw_square():
for i in range(4):
forward(20)
left(90)
Here is the whole program, with the for loop within the function:
from turtle import * def draw_square(): for i in range(4): forward(20) left(90) draw_square() forward(50) right(90) forward(100) draw_square() left(90) forward(20) draw_square() left(90) forward(20) draw_square()
The blank lines do not actually serve any functional purpose. They just make the program more readable. You could have a less readable but still functionally correct program like this:
from turtle import * def draw_square():
for i in range(4): forward(20)
left(90) draw_square() forward(50) right(90) forward(100)
draw_square() left(90) forward(20) draw_square() left(90) forward(20) draw_square()
In the above version, blank lines are placed haphazardly in the program. This is bad programming style, but the program will still work. Blank lines do not determine what is considered part of a for loop or part of a function. Python only pays attention to indentation when determining those things.
Here is a program that uses our forward_backward_twenty
function to draw a plus sign:
from turtle import *
def forward_backward_twenty():
forward(20)
backward(20)
forward_backward_twenty()
left(90)
forward_backward_twenty()
left(90)
forward_backward_twenty()
left(90)
forward_backward_twenty()
left(90)
This program can also be further condensed. Note the repetition:
from turtle import * def forward_backward_twenty(): forward(20) backward(20) forward_backward_twenty() left(90) forward_backward_twenty() left(90) forward_backward_twenty() left(90) forward_backward_twenty() left(90)
Calls to custom functions, like forward_backward_twenty
, can be put in for loops just like other function calls:
from turtle import * def forward_backward_twenty(): forward(20) backward(20) for i in range(4): forward_backward_twenty() left(90)
The theme of the last couple modules has been using Python programming constructs to avoid repetition. Now that you know how to use these constructs - for loops and function definitions - you should do your best to avoid repetition in your code. If you ever find yourself copying and pasting code, stop and ask yourself whether there is a way to condense what you are trying to write.
Dividing your program into functions is also a good way to follow the programming practice of modularity - dividing your program into small, well-defined pieces. Modularity has a few benefits. First, it helps you not repeat yourself (making alterations and maintenance easier). Second, it helps you isolate problems more quickly. It is easier to test several well-defined units by themselves than to test one large system as a whole. Third, it helps you logically divide the problem you are trying to solve into pieces, which in turn helps you stay mentally organized as you try to solve the problem. As you continue to program, the programs you write will be come more and more complicated, and thus more and more difficult to keep in your head all at once. Dividing a program into pieces allows you to concentrate on specific parts of a program without having to simultaneously consider the entire rest of the program.
1. Which of the following is least true about creating your own functions?
a.By creating your own functions, you are creating an alias for a segment of code.
b.Creating your own functions allows you to reuse code that might otherwise have to be written multiple times.
c.By creating your own functions, you can draw pictures with Turtle Graphics that would not be possible to draw without creating your own functions.
d.Creating your own functions can make your code more organized and easy to keep track of.
2. Which of the following lines correctly defines a new function called turn_around
?
func(turn_around):b.
define turn_around:c.
def turn_around():d.
function turn_around():
3. Suppose you have defined the function forward_backward_twenty
from the reading. What would the following code do?
for i in range(4): forward_backward_twenty() left(180) forward_backward_twenty() left(180)a.
It draws a line segment of length 160 going to the right from the origin.
b.It repeatedly draws over the same line segment, extending 20 pixels to either side of the origin.
c.It draws an octagon with edges of length 20 whose bottom left corner is at the origin.
d.It draws a square with edges of length 20 whose bottom left corner is at the origin.
For each of these exercises, you should start by creating a new Turtle Graphics REPL session. You can do this by going to:
https://repl.it/languages/python_turtle
This program tries to draw a triangle using a function to draw each edge. See if you can fix it!
from turtle import *
def draw_edge():
forward(50)
left(120)
for i in range(3):
draw_edge()
When you are finished, your program should draw this:
This program tries to draw a hexagon with edges that alternate between green and blue. Currently, it draws the hexagon twice. See if you can fix it! Hint: the draw_two_edges
function should only draw two edges, and currently, it doesn't.
from turtle import * def draw_two_edges(): for i in range(2): color('green') forward(50) left(60) color('blue') forward(50) left(60) for i in range(3): draw_two_edges()
When you are finished, the program should still look like this but should only have drawn the hexagon once:
Write a Turtle Graphics program that defines the forward_backward_twenty
function from the reading. Use this function to draw a five-pointed star with branches of length 50. You should begin by turning left by 90 degrees, so the first branch of the star extends upwards. Each branch thereafter is separated by the last branch by 72 degrees. Your arrow should finish facing upwards.
When you are finished with your program, it should draw this:
Write a Turtle Graphics program with a function called draw_red_line. This function should change color to red and draw a line segment of length 50 in whatever direction the arrow is currently facing. Don't worry about changing the arrow's color back after you've changed it to red.
You may write code beneath your function to test it. However, when you submit, you should not have any code in your program except your function! The test will add code to your program to make sure your function was written correctly.
Say you call your function like this:
forward(50)
draw_red_line()
left(90)
draw_red_line()
Your program should then draw this:
Write a Turtle Graphics program with a function called draw_red_square
. This function should:
You should not change the arrow's color back after you've changed it to red.
You may write code beneath your function to test it. However, when you submit, you should not have any code in your program except your function! The test will add code to your program to make sure your function was written correctly.
Say you called your function like this:
left(90)
forward(50)
draw_red_square()
forward(100)
Your program should then draw this:
Write a Turtle Graphics program with two functions - one called draw_edge
and one called draw_corner_piece
. You will use these functions to draw the square with corner decorations from a previous exercise.
The draw_corner_piece
function should start assuming that the arrow has just drawn the edge of a square. It should turn the arrow the necessary number of degrees to draw a line segment of length 20 diagonally outwards from the corner that will form between the edge just drawn and the edge about to be drawn. It should then draw the line segment and position the arrow to draw the next edge of the square.
To make that less confusing, pretend that the arrow has just drawn the first edge of a square. It is 50 pixels to the right of the origin and facing right. If you were to call the draw_corner_piece
function immediately after, this should be the result:
You should copy the draw_edge
function from here:
def draw_edge():
forward(50)
draw_corner_piece()
Note that the draw_edge
function calls the draw_corner_piece function.
Now, in the main part of your program below your function definitions, use only the draw_edge
function to draw a full square with four corner pieces, starting at the origin. The bottom left corner of the square (not including the corner decorations) should be at the origin. The arrow should end up at the origin facing right.
When you are finished, your program should draw this: