Python by Projects

unit

Turtle Art Studio

You are the artist. Your robot turtle holds the pen and draws whatever you command. By the end of this unit you will run a spirograph design — one small shape turning into a whole design. Your mission is to discover how a short set of commands makes it.

Each idea comes as a short ladder — simplest first, then one step up — with a Notice naming the one new thing. Every turtle program here also lives in assets/ so you can run it and watch the window.

You will learn

  • Command the turtle to move, turn, lift its pen, and change color and pen size.
  • Repeat a block with a for loop and range().
  • Work out the turn for any polygon with 360 / n, which gives a float.
  • Nest one loop inside another to build a spirograph.

Lesson 1: Move the Pen

import turtle brings in the drawing tools. forward(100) moves the turtle 100 steps; right(90) turns it one square corner. The turtle draws wherever its pen touches the page.

import turtle

turtle.forward(100)
turtle.right(90)

turtle.done()

Notice

forward moves the turtle and right turns it — one move, one turn leaves an open corner.

Turtle drawings open their own window, so this program runs as a file, not in the notebook. Open a terminal in JupyterLab (File ▸ New ▸ Terminal) and move into this unit folder:

cd python-projects/units/unit-03-turtle-art-studio

Then run the file. On Windows, enter:

py assets/l1_corner.py

On a Mac, enter:

python3 assets/l1_corner.py

You can also open assets/l1_corner.py in Thonny and click Run. A drawing window opens (it may hide behind JupyterLab); close it when done.

import turtle

turtle.forward(100)
turtle.right(90)
turtle.forward(100)
turtle.right(90)
turtle.forward(100)
turtle.right(90)
turtle.forward(100)
turtle.right(90)

turtle.done()

Notice

Repeating the same move-and-turn four times draws a closed square — the turtle ends where it began.

Run assets/l1_plain_square.py the same way — a drawing window opens; close it when done.

import turtle

turtle.penup()
turtle.forward(80)
turtle.pendown()

turtle.forward(100)
turtle.right(90)
turtle.forward(100)
turtle.right(90)
turtle.forward(100)
turtle.right(90)
turtle.forward(100)
turtle.right(90)

turtle.done()

Notice

penup() lifts the pen so a move leaves no mark; pendown() drops it again before drawing.

Run assets/l1_travel.py the same way — a drawing window opens; close it when done.

import turtle

turtle.color("blue")
turtle.forward(100)
turtle.right(90)
turtle.forward(100)
turtle.right(90)
turtle.forward(100)
turtle.right(90)
turtle.forward(100)
turtle.right(90)

turtle.done()

Notice

color("blue") changes the pen color — the shape is the same, the ink is different.

Run assets/l1_color.py the same way — a drawing window opens; close it when done.

import turtle

turtle.color("teal")
turtle.pensize(4)

turtle.forward(100)
turtle.right(90)
turtle.forward(100)
turtle.right(90)
turtle.forward(100)
turtle.right(90)
turtle.forward(100)
turtle.right(90)

turtle.done()

Notice

pensize(4) makes the line thicker — a fourth pen setting, separate from color.

Run assets/l1_square.py the same way — a drawing window opens; close it when done.

Lesson 2: Repeat with for and range()

Writing the same two commands four times is a lot of typing. A for loop repeats an indented block, and range(n) runs it exactly n times. The counter starts at 0 and stops before n.

import turtle

for side in range(4):
    turtle.forward(100)
    turtle.right(90)

turtle.done()

Notice

for side in range(4): repeats the block four times — the loop replaces the written-out square.

Run assets/l2_square_loop.py the same way — a drawing window opens; close it when done.

import turtle

angle = 120
for side in range(3):
    turtle.forward(100)
    turtle.right(angle)

turtle.done()

Notice

Change range(3) and the corner turn to draw a triangle — the number of sides is now yours to choose.

Run assets/l2_triangle.py the same way — a drawing window opens; close it when done.

import turtle

n = 7
side_length = 70
angle = 360 / n
for side in range(n):
    turtle.forward(side_length)
    turtle.right(angle)

turtle.done()

Notice

Let Python compute angle = 360 / n. The / always makes a float — a decimal like 360 / 7 = 51.428… — and the turtle turns by it just the same.

Run assets/l2_polygon.py the same way — a drawing window opens; close it when done.

import turtle

n = 7
side_length = 70
angle = 360 / n

turtle.color("blue")
turtle.pensize(2)
turtle.penup()
turtle.forward(20)
turtle.pendown()

for side_number in range(n):
    turtle.pensize(side_number + 1)
    turtle.forward(side_length)
    turtle.right(angle)

turtle.done()

Notice

The loop counter side_number can do work too — here pensize(side_number + 1) makes each side a little thicker than the last.

Run assets/l2_polygons.py the same way — a drawing window opens; close it when done.

Lesson 3: Loops Inside Loops

One loop can live inside another — nested loops. The inner loop draws one whole shape; the outer loop turns the turtle and starts the next.

import turtle

for shape_number in range(2):
    for side_number in range(4):
        turtle.forward(90)
        turtle.right(90)
    turtle.right(180)

turtle.done()

Notice

The inner loop finishes a whole square before the outer loop turns 180° and starts the next — a loop inside a loop.

Run assets/l3_two_squares.py the same way — a drawing window opens; close it when done.

import turtle

for shape_number in range(6):
    for side_number in range(4):
        turtle.forward(60)
        turtle.right(90)
    turtle.right(60)

turtle.done()

Notice

More repeats with a smaller turn between them — six squares fan out into a ring.

Run assets/l3_rings.py the same way — a drawing window opens; close it when done.

Put it together: the gallery spirograph nests the same two loops, using angle = 360 / n for the shape and a small turn_between_shapes for the outer sweep. Compare the result with the spirograph promised at the start of the unit — you now know what both loops are doing.

import turtle

n = 6
side_length = 80
angle = 360 / n
shape_count = 24
turn_between_shapes = 15

turtle.color("purple")
turtle.pensize(2)

for shape_number in range(shape_count):
    for side_number in range(n):
        turtle.forward(side_length)
        turtle.right(angle)
    turtle.right(turn_between_shapes)

turtle.done()

Run assets/l3_spirograph.py the same way — a drawing window opens; close it when done.

Recap

  • forward, right, penup, pendown, color and pensize control the turtle's pen.
  • for side in range(n): repeats a block exactly n times, counting from 0.
  • angle = 360 / n gives the turn for an n-sided shape, and / always makes a float.
  • The loop counter can do work too, such as making each side thicker.
  • In nested loops the inner loop draws a whole shape before the outer loop turns and starts the next.

You can now design and run a spirograph of your own.

Go to the exercises (12)

For parents and teachers: report a problem