Back to Table of Contents

Skip to Reading Quiz

Skip to Exercises

Turtle Graphics (Loops)

This reading will teach you how to repeat certain pieces of your program using something called a loop.

One of the most important principles in programming is: don't repeat yourself (often abbreviated DRY). Loops help you follow this principle in your code.

If you'd like to follow along, open the following URL in a separate tab or window:

https://repl.it/languages/python_turtle

Motivation

Let's say you want to use Turtle Graphics to draw a square. You might draw one edge of the square like this:

from turtle import *

forward(50)
left(90)

A REPL window. The left side contains the code written above this image. The right side has the result of running the code, which is a single black line segment of length 50 going to the right of the origin. The arrow is black, is at the right end of the line segment, and is facing up.

The left turn puts the arrow in position to draw the next edge of the square. You can then complete the square by repeating the same lines three more times, like this:

from turtle import *

forward(50)
left(90)
forward(50)
left(90)
forward(50)
left(90)
forward(50)
left(90)

A REPL window. The left side contains the program written just before this image. The right side has the result: a square whose bottom left corner is the origin and whose sides are black and of length 50. The arrow is black and is at the origin facing to the right.

Technically, we don't need the last left turn here. However, I'm including it for two reasons. First, it is nice to leave the arrow facing the same direction it faced at the beginning. Second, we are about to change this program slightly, and the change will be more transparent if we leave one last left turn at the end.

The program above is quite repetitive. Repetitive code is problematic for a couple reasons:

  1. It is a pain to type that much, especially when we're typing the same thing over and over. (Okay, I guess you can copy and paste. But beware of doing this because of reason 2!)
  2. This is the more important reason. Repetitive code is difficult to change, and changing it can be error-prone.

Let's dive into the second reason. Say you change your mind about the size of the square you want. You want it to have edges of length 60 instead of 50. To make this change, you have to remember to change all four instances of the number 50 to the number 60, resulting in the following program:

from turtle import *

forward(60)
left(90)
forward(60)
left(90)
forward(60)
left(90)
forward(60)
left(90)

This is a lot of time and effort for what seems like a small change in the logic of the program. Also, there is a chance that you'll forget to change one of the numbers, causing your program to produce an incorrect result! (I'd recommend trying this so you can see what happens.) In general, the more you repeat yourself:

Now, you might be thinking: "Changing four numbers isn't that bad, and I doubt I'd miss one." Now imagine you want to repeat something 100 times, or 1,000,000 times. This is often necessary in programming, and it makes the task above much more daunting.

Loops to the Rescue!

Fortunately, Python (like other major programming languages) has a programming construct called a for loop that allows the programmer to repeat a section of their program without having to type it multiple times. Let's return to the square with edges of length 50. This is what the program looks like with a for loop:

from turtle import *

for i in range(4):
forward(50)
left(90)

There is quite a bit to unpack with this new syntax, so let's break it down into pieces. First, take a look at the first line:

for i in range(4):

For now, don't worry about i or range. Note the number 4, which indicates that this for loop will repeat something 4 times. In general, if you want to repeat a section of code a certain number of times, the first line of your for loop should follow this template:

for i in range(   ):

The blank space between the parentheses should contain the desired number of repetitions. Everything else must be just so: you must start with the word for, there must be parentheses after the word range, and there must be a colon at the end. For now, please use the letter i after the word for. Later in this class, you'll be able to use other things.

Now, let's take a look at the lines of code after the for line:

    forward(50)
left(90)

Notice that both lines have been indented slightly. This is important. This indicates that both lines are part of the section that should be repeated. They are described as being in the for loop. They can also be described as the body of the for loop. Both lines must be indented by the same amount.

A for loop works like this: Python sees the line starting with for and recognizes that it should repeat whichever lines of code have been indented immediately after the for line. Python executes each command in the for loop in order before cycling back to the beginning. So, in this case, both the forward command and the left command are executed for the first time before Python loops back and starts repeating. Python does not repeat the forward command 4 times in a row and then repeat the left command 4 times in a row.

Examples

Multi-Color Line

Here is a program that uses a for loop to draw a line with alternating colors:

from turtle import *

for i in range(3):
color('blue')
forward(30)
color('green')
forward(30)

This is a REPL window. The left side shows the program written above this image. The right side shows the result: a green arrow at the end of a 180-pixel line made of 30-pixel segments that alternate blue, green, blue, green, blue, green. The line goes to the right from the origin, and the arrow faces to the right.

When looking at a program that contains a for loop, it can be helpful to unravel the for loop to more easily visualize what the program does. Here is the same program with the for loop deconstructed:

from turtle import *

color('blue')

forward(30)
color('green')
forward(30)
color('blue')
forward(30)
color('green')
forward(30)
color('blue')
forward(30)
color('green')
forward(30)

I've made the first four lines bold to make it clear that these are the same for lines that appear in the body of the for loop above. The deconstructed program is just these four lines repeated three times.

Multi-Color Square

Below is a program that draws a square. It might seem like this program draws four edges that are each half black and half red. However, only one edge is half one color and half another. The other three edges are all red!

from turtle import *

for i in range(4):
forward(20)
color('red')
forward(20)
left(90)

A REPL window. The left side shows the program described above the image. The right side shows the result. It is a square where the bottom edge extends to the right from the origin by 40 pixels divided into one 20-pixel black segment and one 20-pixel red segment. The next edge goes upwards and is all red, and there is a mark indicating that the arrow stopped halfway through. The third edge extends to the left from the top of the second edge, is all red, and also has a mark halfway through. The fourth edge extends downwards back to the origin, is all red, and also has a mark halfway through. The arrow is left facing to the right, with the point on the origin, and it is red.

To understand why this program does what it does, it is once again useful to deconstruct the for loop. Below is the same program, deconstructed. I've added small notes in the program. These notes are called comments, and as long as you use the pound sign (#), you can include these comments in your code, too. We will cover comments in more detail in a future module.

from turtle import *

forward(20)
# At this point, the arrow's color is black.
color('red') # Now, it is red.
forward(20)
left(90)
# This is where we start repeating the same commands over again.
# However, that doesn't mean the color has changed back to black!
# It is still red.
forward(20)
color('red') # This line basically does nothing.
forward(20)
left(90)
forward(20)
color('red') # Whoops, the arrow is still red!
forward(20)
left(90)
forward(20)
color('red')
forward(20)
left(90)

Common Mistakes

It is easy to forget the indentation rules with for loops. You might accidentally indent the lines of code in a for loop by different amounts, like this:

from turtle import *

for i in range(3):
color('blue')
forward(20)
color('green')
forward(20)

If you do this, Python will show you an error message in the console tab on the right side:

A REPL window. The code above is on the left side. The first forward(20) is indented by only three spaces instead of four. The second forward(20) is indented by five spaces instead of four. The right side is switched to the console tab, and the error message reads: "IndentationError: unindent does not match any outer indentation level on line 5". The error message then shows the line forward(20) and has a carat below pointing to the f in forward.

Now, suppose you don't indent the body at all:

from turtle import *

for i in range(3):
color('blue')
forward(20)
color('green')
forward(20)

Then, you'll see this:

A REPL window. The code above is on the left side. None of the four lines under the "for" line is indented. The right side is switched to the console tab, and the error message reads: "ParseError: bad input on line 4".

Finally, suppose you forget to indent some of the later lines in the for loop:

from turtle import *

for i in range(3):
color('blue')
forward(20)
color('green')
forward(20)

This is a valid program, but it might not do what we want. Python will only consider the first two lines as the body of the for loop. It will then run the for loop to completion before reaching the line that changes the color to green. Here is what that looks like:

A REPL window. The code above is on the left side. Only the first two lines after the "for" line are indented. The other two have no indentation. On the right, the result is a line segment of length 80 divided into four 20-pixel sections. The first three sections are blue and the last section is green. The line segment extends to the right from the point of origin. The arrow is green and faces to the right at the right end of the line segment.

When to Loop

If you notice yourself doing something two or more times in a row, a loop might come in handy.

Say you want to draw a plus sign, for example. You might write that program like this:

from turtle import *

forward(50)
backward(50)
left(90)
forward(50)
backward(50)
left(90)
forward(50)
backward(50)
left(90)
forward(50)
backward(50)

The left side of the REPL window shows the program written above this image. The right side shows the result, which is a plus sign with black branches of length 50 whose center is the origin. The arrow is black and is facing downwards with its tip at the origin.

Each forward/backward combo draws one branch of the plus sign. Turning to the left by 90 degrees after each branch is drawn puts the arrow in position to draw the next branch.

Notice that one part of this program repeats three times in a row:

from turtle import *

forward(50)
backward(50)
left(90)
forward(50)
backward(50)
left(90)
forward(50)
backward(50)
left(90)
forward(50)
backward(50)

We can compress this code by writing one copy of the highlighted sequence in the body of a for loop that cycles three times, like this:

from turtle import *

for i in range(3):
forward(50)
backward(50)
left(90)
forward(50)
backward(50)

Now, the program is shorter, and it will be much easier to change.

Depending on how important it is that the arrow faces a certain direction at the end, we can actually reduce this program in size even more by adding a line at the end:

from turtle import *

forward(50)
backward(50)
left(90)
forward(50)
backward(50)
left(90)
forward(50)
backward(50)
left(90)
forward(50)
backward(50)
left(90)

By adding the left command at the end, we've turned the last two lines (which previously had to be left outside the for loop) into three lines that exactly match the repeated sequence above them:

from turtle import *

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, we can compress the entire program into a single for loop that cycles four times, like this:

from turtle import *

for i in range(4):
forward(50)
backward(50)
left(90)

The only functional difference is that the arrow will be facing to the right at the end instead of downwards.

Not only is this program even shorter and even easier to maintain, it makes more sense logically when we think about what we are trying to accomplish. To draw a plus sign, you have to draw the four branches of a plus sign. This maps very nicely to a program that repeats the same actions four times.

The Letter i

I will now add one small wrinkle to the concept of a for loop. The letter i actually has significance in the loop. It is an example of a variable, something that will be covered in more detail in a future module. Think of a variable as a name that stands for a piece of information. In this case, the variable's name is the letter i, and it stands for a number. In particular, it represents which cycle of the for loop the program is currently executing.

The variable i is really only meaningful if you use it in your code. To see the lifecycle of the variable i, let's take the plus sign program from earlier and add a line to it, like this:

from turtle import *

for i in range(4):
print(i)
forward(50)
backward(50)
left(90)

The program now uses a new command: the print command. This command does not affect what the arrow does in the "result" tab:

The left side of the REPL window contains the program written above. The right side displays the result tab, which shows a black plus sign with branches of length 50 centered on the origin. The arrow is black and is facing to the right with the tip on the origin. The console tab has an exclamation mark on the tab itself, denoting that the console has content.

Instead, it outputs information in the "console" tab:

The left side of the REPL window contains the same program as the last image (the program most recently given in the reading). The right side is on the console tab, which shows the numbers 0, 1, 2, and 3, each printed on their own line. The console tab has an exclamation mark on the tab itself, denoting that the console has content.

Here's what happened in the console: each time Python started a cycle of the for loop, it executed the print command, which output whatever number i stood for in that moment. The first cycle, i stood for 0; the second cycle, i stood for 1, etc. If you were to watch both the result tab and the console tab simultaneously, each number would appear just before that branch of the plus sign is drawn.

The fact that counting starts at zero can be a challenging one to remember for novice programmers. However, this fact applies to more than just for loops. As we'll see in future modules, whenever something can be numbered sequentially in a program, generally, that numbering starts at zero.

Now for something even crazier: the variable i can be used in place of numbers in commands like forward and left! Take a look at this program:

from turtle import *

for i in range(5):
forward(i)
left(90)

The left side of the REPL window shows the program above. The right side shows a line of length 1 going up from the origin, a line of length 2 going left from the end of the first line, a line of length 3 going down from the end of the second line, and a line of length 4 going right from the end of the third line. All lines are black. The arrow is black and is facing up with its tip at the end of the last line.

This program doesn't seem to produce much, but if you look closely, you can see that the arrow went forward by 0, then by 1, then by 2, etc. In other words, it is going forward by whatever i stands for during that cycle.

We can make the spiral effect more exaggerated by having the arrow go forward not by i, but by i times 10, using the multiplication operator (an asterisk):

from turtle import *

for i in range(5):
forward(i * 10)
left(90)

The left side of the REPL window shows the program above. The right side shows a line of length 10 going up from the origin, a line of length 20 going left from the end of the first line, a line of length 30 going down from the end of the second line, and a line of length 40 going right from the end of the third line. All lines are black. The arrow is black and is facing up with its tip at the end of the last line.

Now, we can see that the arrow went forward by 0 (0 * 10), turned left, went forward by 10 (1 * 10), turned left, went forward by 20 (2 * 10), turned left, etc.

Reading Quiz

Back to Top

1. Which of the following is the correct first line of a for loop that will repeat a piece of code 4 times?

a.
while in range(4):
b.
repeat(4):
c.
for i in range(4):
d.
range(4) repeat:

2. What would the following program draw?

from turtle import *

for i in range(3):
    left(90)
a.

It would draw three sides of a square.

b.

It would not draw anything. The arrow would just rotate.

c.

It would draw a 90-sided shape.

d.

It would draw a triangle.

3. Which of the following programs would not draw a square whose sides are all blue?

a.
from turtle import *

for i in range(4):
    forward(50)
    color('blue')
    left(90)
b.
from turtle import *

for i in range(4):
    color('blue')
    forward(50)
    left(90)
c.
from turtle import *

for i in range(4):
    left(90)
    color('blue')
    forward(50)
d.
from turtle import *

color('blue')
for i in range(4):
    forward(50)
    left(90)

Exercises

Back to Top

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

Exercise 1.0

This program tries to draw a square. Copy the code into a new Turtle Graphics REPL session and see if you can fix it!

from turtle import *

for i in range(4):
forward(50)
left(90)

When the program is fixed, it should draw this:

A black square with edges of length 50 and with its bottom left corner at the origin. The arrow is black and is facing right with its tip at the origin.

Exercise 1.1

This program tries to draw a plus sign. Copy the code into a new Turtle Graphics REPL session and see if you can fix it!

from turtle import *

for i in range(3):
forward(50)
backward(50)
left(90)

When the program is fixed, it should draw this:

A black plus sign with branches of length 50 and with its center at the origin. The arrow is black and is facing right with its tip at the origin.

Exercise 1.2

Write a Turtle Graphics program that uses a for loop to draw a black diamond with sides of length 50. For the purpose of this exercise, a diamond is just a square rotated by 45 degrees. You may need some code outside your for loop in order to complete this exercise.

When you are finished, your program should draw this:

A black square rotated 45 degrees with its bottom corner at the origin. The arrow is black and is facing right with its tip at the origin.

Exercise 1.3

Write a Turtle Graphics program that uses a for loop to draw a black square with edges of length 50 and with small line segments of length 20 extending outwards diagonally (at an angle of 135 degrees from either adjacent side) from the corners. The square itself should not be rotated - its bottom edge should be parallel with the bottom of the screen.

When you are finished, your program should draw this:

A black square with sides of length 50 and with its bottom left corner at the origin. From each corner, there is a line segment of length 20 extending outwards diagonally such that it makes a 135 degree angle with either adjacent square edge. The arrow is black and is facing right with its tip at the origin.

Exercise 1.4

Write a Turtle Graphics program that uses a for loop to draw a black equilateral hexagon with sides of length 50. Hint: this is similar to drawing a square, except there are six sides and the inner angle is 120 degrees (meaning you should turn by 60 degrees if you are going forward or 120 degrees if you are going backward). The hexagon should not be rotated - its bottom edge should be parallel with the bottom of the screen.

When you are finished, your program should draw this:

A black hexagon with sides of length 50 and with the leftmost point of its bottom edge at the origin. The arrow is black and is facing right with its tip at the origin.

Exercise 1.5

Modify your program from the last exercise so it divides the hexagon into six equilateral triangles. You should not draw any line segments that extend all the way from one corner of the hexagon to another. All inner line segments should extend only as far as the center of the hexagon (so they should start or end at the center).

When you are finished, your program should draw this:

A black equilateral hexagon with sides of length 50 and with the leftmost point of its bottom edge at the origin. The hexagon has been divided by black line segments into six equilateral triangles, each of which has one point at the center of the hexagon and two points at the endpoints of one of the hexagon's edges. The arrow is black and is facing right with its tip at the origin.

Back to Top

Back to Table of Contents