Learning Goals
3 minBy the end of this lesson you can:
- Define the Koch curve recursively: each line becomes four shorter lines at angles +60°, -120°, +60°.
- Build a Koch curve function in turtle that recurses to a given depth.
- Compose three Koch curves into a snowflake by turning -120° between them.
- Recognise how perimeter grows infinitely while area stays bounded.
Warm-Up · The Koch Recipe
5 minA line, depth 0: ─────────
depth 1 — replace with 4 lines: /\
───/ \───
depth 2 — replace EACH of those 4 lines:
smaller bumps on every segment
depth 3 — replace each of those new lines:
even smaller bumps everywhereEach line is replaced by four lines, each ⅓ the length. After 5 levels, the curve has 4⁵ = 1024 tiny segments.
The Koch curve is self-similar like yesterday's tree — but instead of branching off the trunk, the recursion replaces each line with a more complex version of itself.
New Concept · The Koch Function
14 minThe base case · just draw a line
def koch(length, depth): if depth == 0: t.forward(length) return # ... recursive case below
The recursive case · four shorter lines
Each line at depth N gets replaced by four lines at depth N-1, each ⅓ as long. The turn pattern is +60°, -120°, +60° — between the four segments.
def koch(length, depth): if depth == 0: t.forward(length) return third = length / 3 koch(third, depth - 1) t.left(60) koch(third, depth - 1) t.right(120) koch(third, depth - 1) t.left(60) koch(third, depth - 1)
Five lines of recursive code. Four self-calls. Three angle changes. Beautiful.
The angles · why 60 and 120?
Imagine the bump is an equilateral triangle:
/\ peak is 60° rotation from the base
/ \ the two slopes are 60° on each side
___/ \___ after the peak, turn -120° to come back down
(back to the original heading at the end)Net heading change: +60 -120 +60 = 0. The end of each koch call leaves the turtle facing the same way it started — essential for stacking.
The full snowflake
A snowflake = three Koch curves forming a triangle. Between each, turn -120° (since the triangle's exterior angle is 120°).
def snowflake(length, depth): for _ in range(3): koch(length, depth) t.right(120)
Three sides. Each side is a Koch curve. Together they form a closed snowflake.
The infinite-perimeter paradox
At each level, the total perimeter grows by 4/3 (each segment becomes 4 ⅓-length segments). After infinite iterations the perimeter is infinite — but the snowflake fits inside a finite circle. An infinitely-long boundary enclosing a finite area. Maths is wild.
You won't see the infinity on your screen — at depth 5, segments are about 1 pixel long and the recursion just renders solid-looking lines.
Worked Example · The Snowflake
12 minSave as snowflake.py:
# snowflake.py — Koch snowflake at depth 4 import turtle as t screen = t.Screen() screen.setup(width=800, height=800) screen.bgcolor("midnightblue") screen.colormode(255) t.speed(0) t.hideturtle() t.color(220, 240, 255) # icy white-blue t.pensize(2) def koch(length, depth): if depth == 0: t.forward(length) return third = length / 3 koch(third, depth - 1) t.left(60) koch(third, depth - 1) t.right(120) koch(third, depth - 1) t.left(60) koch(third, depth - 1) def snowflake(length, depth): for _ in range(3): koch(length, depth) t.right(120) # Position so it's centred t.penup() t.goto(-250, 150) t.setheading(0) t.pendown() snowflake(length=500, depth=4) t.done()
What you'll see
A glowing snowflake on a dark blue background. At depth 4 you can pick out individual bumps; at depth 5 the curve looks almost smooth.
Read the diff
Two functions, one outer loop. koch is purely recursive. snowflake just runs koch three times with a 120° turn between. Total recursive calls at depth 4: 4⁴ × 3 = 768. The image emerges from 768 tiny forward() calls, all positioned automatically by the recursion.
Depth 4: 256 segments per side, fast. Depth 5: 1024, slower but smoother. Depth 6: 4096 — minutes to draw. Past 6, segments are sub-pixel and you can't tell. t.speed(0) is non-negotiable.
Try It Yourself
13 minComment out the snowflake call. Just draw koch(600, 4). Look at the bumpy line on its own.
Change the bumps to go inward instead of outward. Swap the left/right calls. You get an "anti-snowflake".
Hint
def koch_inward(length, depth): if depth == 0: t.forward(length) return third = length / 3 koch_inward(third, depth - 1) t.right(60) # changed from left koch_inward(third, depth - 1) t.left(120) # changed from right koch_inward(third, depth - 1) t.right(60) # changed from left koch_inward(third, depth - 1)
Bumps point inwards. The shape looks more like a star or a snowflake-with-jagged-cuts.
Replace each line with FIVE shorter lines in a square bump pattern (up, across, down, across, up — back to base). The angles are +90°, -90°, -90°, +90°. Apply recursively.
Hint
def koch_square(length, depth): if depth == 0: t.forward(length) return fifth = length / 5 # not 4 — see below koch_square(fifth, depth - 1) t.left(90) koch_square(fifth, depth - 1) t.right(90) koch_square(fifth, depth - 1) t.right(90) koch_square(fifth, depth - 1) t.left(90) koch_square(fifth, depth - 1)
5 segments, ⅕ length each. The angles +90-90-90+90 net to 0 — the turtle ends facing forward again.
Mini-Challenge · Five-Snowflake Gallery
8 minDraw five snowflakes in a row, at depths 0, 1, 2, 3, 4. The viewer sees the recursion grow before their eyes — what depth 0 looks like (a triangle), depth 1 (a Star of David), depth 2-4 (increasingly bumpy snowflakes).
Show one possible solution
# gallery.py — five snowflakes at depths 0-4 import turtle as t screen = t.Screen() screen.setup(width=1400, height=400) screen.bgcolor("midnightblue") screen.colormode(255) t.speed(0) t.hideturtle() t.color(220, 240, 255) def koch(length, depth): if depth == 0: t.forward(length) return third = length / 3 koch(third, depth - 1) t.left(60) koch(third, depth - 1) t.right(120) koch(third, depth - 1) t.left(60) koch(third, depth - 1) def snowflake(length, depth): for _ in range(3): koch(length, depth) t.right(120) def jump_to(x, y): t.penup() t.goto(x, y) t.setheading(0) t.pendown() for i, depth in enumerate(range(5)): jump_to(-650 + i * 260, 80) snowflake(length=180, depth=depth) t.done()
Non-negotiables: one koch + one snowflake function, called five times in a row at depths 0-4. The progression is the point — viewers SEE what depth changes do.
Recap
3 minThe Koch curve is a line-replacement recursion. Each line becomes four shorter lines with angles +60°, -120°, +60°. Three Koch curves with 120° turns between form a snowflake. Each call returns the turtle to its original heading. Depth budget: 4-5 is usually right for screen-size drawings; past 6 segments are sub-pixel. Mathematically infinite perimeter, finite area — fractal weirdness.
Vocabulary Card
- Koch curve
- The line-replacement fractal. Each line becomes four shorter lines.
- Koch snowflake
- Three Koch curves arranged as the sides of a triangle.
- line replacement
- The recursion shape: substitute each segment with a smaller version of a more complex shape.
- heading preservation
- The recursive function's angle changes net to zero — turtle ends pointing the same way.
Homework
4 minBuild my_fractal.py with two variations:
- Star Koch snowflake. Same code, but apply the koch transformation to each side of a 5-sided star instead of a 3-sided triangle. Turn 144° between sides (5-point star external angle).
- Random-bump Koch. The bump can go in either direction (up or down) at random. Use
random.choicefor the sign of the angle. Run with a seed; you get organic-looking coastlines.
Sample · random-bump Koch (coastline)
import random def koch_random(length, depth): if depth == 0: t.forward(length) return third = length / 3 sign = random.choice([1, -1]) # bump up or down at random koch_random(third, depth - 1) t.left(60 * sign) koch_random(third, depth - 1) t.right(120 * sign) koch_random(third, depth - 1) t.left(60 * sign) koch_random(third, depth - 1) random.seed(42) koch_random(800, 5) t.done()
Non-negotiables: a Koch variant that either changes the polygon (star) or randomises the bump direction. Different seeds → different coastlines from the same code.