Part 2: Core Programming Concepts

6. Functions & Modular Programming

Packaging logic into reusable units

A function is a named block of code that performs one job. You define it once and call it as many times as you like. Functions are the heart of modular programming: instead of one giant script, you build small, named pieces that each do one thing well and fit together.

width → 4 height → 3 area(w, h) return w * h 12 parameters in · result out

Defining and calling

To define a function you give it a name, list the inputs it expects, and write the body. To use it, you call it by name and supply values.

def greet(name):            # define; 'name' is a parameter
    print("Hello, " + name)

greet("Ada")               # call; "Ada" is the argument
greet("Grace")             # reuse with a different argument

Parameters and arguments

A parameter is the placeholder named in the definition; an argument is the actual value you pass when calling. A function can take several parameters, and the order you pass arguments usually matters.

Return values

Printing shows something to the user; returning hands a value back to the code that called the function, so it can be stored or used in further calculation. A function that returns is like a small machine: inputs go in, a result comes out.

def area(width, height):
    return width * height

a = area(4, 3)     # a is 12
total = area(4, 3) + area(2, 2)   # 12 + 4 = 16

The difference between print and return trips up many beginners: a printed value appears on screen but is gone; a returned value can be captured in a variable and reused.

Scope

Scope is the region of a program where a name is visible. Variables created inside a function are local: they exist only while the function runs and cannot be seen from outside. This isolation is a feature — it means a function cannot accidentally clobber variables elsewhere, so you can reason about it on its own.

def add_tax(price):
    tax = price * 0.1     # 'tax' is local
    return price + tax

print(add_tax(100))        # 110
# print(tax)  -> ERROR: 'tax' does not exist out here

DRY: Don't Repeat Yourself

The deepest reason for functions is DRY — "Don't Repeat Yourself." If the same logic appears in three places and you later find a bug, you must fix it three times and will probably miss one. Put the logic in a function and call it three times, and there is a single place to read, test and correct. Good functions have clear names, do one job, and are short enough to understand at a glance.

Key idea: functions package logic behind a name so it can be reused and tested in isolation; parameters feed them, return values hand results back, and scope keeps their internals private.