Learning LibraryCore Coding LibraryTeens

Functions in Python: name it once, reuse it everywhere

A function packages logic under a name. Write spawn_wave(6) once, and every level that needs a fleet just calls it — no copy-paste, no drift.

The big idea

A function bundles a block of code under a name (with optional inputs), so you can run it — and change it in one place — by calling that name.

See it in code

1The basics

A function packages a block of code under a name. def start_level(): names the block; the indented lines are its body. Defining it changes nothing — you have to call it to run it:

python
def start_level():
    print("Level 1")
    print("Get ready...")

start_level()
Run it — the call runs the whole body:
Level 1
Get ready...

Two lines, one name. start_level() runs the body; change the body once and every call gets the update.

2A step further

Give the function an input and it does a family of jobs. spawn_wave(n) takes a count and loops, computing an evenly spaced x for each enemy — one definition, any size wave:

python
def spawn_wave(n):
    for i in range(n):
        print("enemy at x =", 55 + i * 74)

spawn_wave(3)
Run it — three enemies, three positions:
enemy at x = 55
enemy at x = 129
enemy at x = 203

The parameter n decides how many. Right now it only prints the positions — next we make it build real enemies.

3In our world

Now the real version. Swap the print for an actual Enemy, and return the whole list so the caller can draw it. Same spawn_wave(n) shape — it just hands back objects instead of printing:

python
from game import Stage, Enemy

screen = Stage.create()
Stage.clear(screen)

def spawn_wave(n):
    return [Enemy(55 + i * 74, 90) for i in range(n)]

wave = spawn_wave(6)
for enemy in wave:
    enemy.draw(screen)
Run it — spawn_wave(6) builds the fleet, the loop draws it:
A row of six purple enemy sprites evenly spaced near the top of a dark play area.

Level two wants ten enemies? spawn_wave(10). The spawning logic lives in exactly one place — that is the DRY principle: Don't Repeat Yourself.

The same idea, everywhere

Any repeated logic deserves a function: moving_average(prices, n) in a trading bot, reverse_complement(dna) in biotech, hash_block(data) in a blockchain. Define the behavior once, test it once, and every caller benefits — including the future you who fixes a bug in a single spot.

Try it yourself

Add a y parameter — def spawn_wave(n, y): — then call spawn_wave(6, 90) and spawn_wave(6, 160) to stack two rows. Next, have the function print(len(...)) before it returns, to confirm the count.

The common mistake

Confusing defining with calling. def spawn_wave(n): only describes the function; the code inside never runs until you write spawn_wave(6). And a function that builds a list but forgets to return it hands back None.

What it unlocks

Functions become flexible with arguments, hand back results through return values, and introduce scope — the rule for which variables live inside a function versus outside.

Want the simpler version? Read the Kids version →