← Back to course

Functions: Reusing Code

Functions: Reusing Code

Welcome back.

In the previous lesson, you learned dictionaries.

Your programs learned how to store structured data with keys and values.

You wrote things like:

user = {
    "name": "Anna",
    "age": 25,
    "city": "Rome"
}

Very good.

Now your programs can store meaningful data.

Not just random values floating around like confused balloons.

But now we have another problem.

What if we need to reuse the same code?

For example:

print("Hello, Anna!")
print("Welcome to the program.")
print("Have a nice day!")

Then later:

print("Hello, Marco!")
print("Welcome to the program.")
print("Have a nice day!")

Then later again:

print("Hello, Sofia!")
print("Welcome to the program.")
print("Have a nice day!")

This works.

But it is repetitive.

And repetitive code is dangerous.

Because one day you need to change something.

Then you must change it in five places.

Then you forget one place.

Then the bug appears.

Then coffee becomes emergency fuel.

Functions solve this problem.

Functions let you reuse code.

You write code once.

Then you call it whenever you need it.

Very useful.

Very clean.

Very Python.

What You Will Learn

In this lesson, you will learn:

By the end of this lesson, your code will become more organized.

Less repetition.

More structure.

Fewer copy-paste disasters.

Hopefully.

Functions are one of the biggest steps in programming.

Before functions, code is a long road.

After functions, code becomes a city with signs.

Still possible to get lost.

But at least now there are signs.

What Is a Function?

A function is a reusable block of code.

You define it once.

Then you can use it many times.

Example:

def say_hello():
    print("Hello!")

This creates a function called:

say_hello

But creating a function does not run it.

To run the function, you must call it:

say_hello()

Full example:

def say_hello():
    print("Hello!")

say_hello()

Output:

Hello!

A function is like a small machine.

You build it once.

Then you press the button.

The button is the function call.

Very technical.

Very button.

Your First Function

Create a file:

functions.py

Write:

def greet():
    print("Hello from a function!")

greet()

Run it:

python functions.py

or:

python3 functions.py

Output:

Hello from a function!

This line creates the function:

def greet():

This line belongs to the function:

    print("Hello from a function!")

This line calls the function:

greet()

Important:

def creates the function.
Calling the function runs it.

If you only define a function and never call it, nothing happens.

Python is polite.

It does not run functions unless you ask.

Unlike some people who give advice without being asked.

Function Syntax

A basic function looks like this:

def function_name():
    code_here

Example:

def show_menu():
    print("1. Add item")
    print("2. Show items")
    print("q. Quit")

Parts:

def              starts the function definition
function_name    the name of the function
()               parentheses
:                starts the function body
indentation      code inside the function

The colon is important.

The indentation is important.

Python still cares about indentation.

Very much.

Python sees indentation like a building plan.

If the indentation is wrong, the building collapses.

Digitally.

Calling a Function Many Times

Functions can be called many times.

Example:

def say_hello():
    print("Hello!")

say_hello()
say_hello()
say_hello()

Output:

Hello!
Hello!
Hello!

The function was written once.

But it ran three times.

This is the power of functions.

No copy-pasting the same code everywhere.

You create one reusable block.

Then you use it when needed.

Very clean.

Very civilized.

Very unlike a messy folder called final_final_REAL_final.py.

Why Functions Are Useful

Functions help you:

Without functions, a program can become one long river of code.

A scary river.

With functions, you can split the program into smaller parts.

Example:

show menu
get user choice
add task
show tasks
quit program

Each part can become a function.

This makes your code easier to understand.

Your future self will thank you.

Maybe.

Future self is often tired.

Indentation in Functions

Code inside a function must be indented.

Correct:

def greet():
    print("Hello!")

Wrong:

def greet():
print("Hello!")

Python will show:

IndentationError

The indented lines belong to the function.

Example:

def greet():
    print("Hello!")
    print("Welcome!")

print("This is outside the function.")

Here:

print("Hello!")
print("Welcome!")

belong to the function.

This line:

print("This is outside the function.")

does not belong to the function.

Indentation decides ownership.

Like paperwork.

But with spaces.

Function Names

Function names should be clear.

Good:

def show_menu():
    print("Menu")

Good:

def calculate_total():
    print("Calculating...")

Bad:

def x():
    print("Something")

Bad:

def do_stuff():
    print("Stuff")

Use names that explain what the function does.

Function names usually use lowercase letters and underscores:

show_menu
calculate_total
add_product
get_user_name

This style is called snake_case.

Python likes snake_case.

Not actual snakes.

Probably.

Parameters

A parameter lets a function receive data.

Example:

def greet_user(name):
    print(f"Hello, {name}!")

Here:

name

is a parameter.

It is like an input variable for the function.

Now call the function:

greet_user("Anna")
greet_user("Marco")
greet_user("Sofia")

Full example:

def greet_user(name):
    print(f"Hello, {name}!")

greet_user("Anna")
greet_user("Marco")
greet_user("Sofia")

Output:

Hello, Anna!
Hello, Marco!
Hello, Sofia!

The function is reusable.

The message changes depending on the value you pass.

Very useful.

Very clean.

Very less copy-paste.

Arguments

When you call a function, the value you pass is called an argument.

Example:

def greet_user(name):
    print(f"Hello, {name}!")

greet_user("Anna")

Here:

name

is the parameter.

And:

"Anna"

is the argument.

Simple explanation:

parameter = variable in the function definition
argument  = actual value passed when calling the function

People often use these words casually.

Do not panic.

The important idea is:

Functions can receive values.

That is the part that matters most.

Function with Two Parameters

A function can have more than one parameter.

Example:

def greet_user(name, city):
    print(f"Hello, {name} from {city}!")

Call it:

greet_user("Anna", "Rome")

Full example:

def greet_user(name, city):
    print(f"Hello, {name} from {city}!")

greet_user("Anna", "Rome")
greet_user("Marco", "Milan")

Output:

Hello, Anna from Rome!
Hello, Marco from Milan!

The order matters.

This:

greet_user("Anna", "Rome")

means:

name = Anna
city = Rome

If you switch them:

greet_user("Rome", "Anna")

Output:

Hello, Rome from Anna!

Technically correct.

Emotionally strange.

Functions and Calculations

Functions are great for calculations.

Example:

def add_numbers(a, b):
    total = a + b
    print(total)

add_numbers(5, 3)

Output:

8

Here:

a
b

are parameters.

This function adds them and prints the result.

Another example:

def calculate_total(price, quantity):
    total = price * quantity
    print(f"Total: {total:.2f}")

calculate_total(10.00, 3)

Output:

Total: 30.00

This is useful.

But there is a better way.

Instead of only printing the result, we can return it.

That is where return enters.

Very important.

Very function.

Returning Values

A function can return a value.

Example:

def add_numbers(a, b):
    return a + b

result = add_numbers(5, 3)

print(result)

Output:

8

The function:

def add_numbers(a, b):
    return a + b

does not print.

It gives the result back.

This line stores the result:

result = add_numbers(5, 3)

Then we print it:

print(result)

This is very important.

A function that returns a value is more flexible.

You can print the value.

Or save it.

Or use it in another calculation.

Or pass it to another function.

This is where functions become powerful.

print() vs return

This is very important.

print() shows something on the screen.

return sends a value back from the function.

Example with print():

def add_numbers(a, b):
    print(a + b)

result = add_numbers(5, 3)

print(result)

Output:

8
None

Why None?

Because the function printed the result, but did not return anything.

Now example with return:

def add_numbers(a, b):
    return a + b

result = add_numbers(5, 3)

print(result)

Output:

8

Simple rule:

Use print() to show something.
Use return to give a value back.

This is one of the biggest beginner lessons.

Very important.

Very easy to confuse.

Very normal.

Function That Returns a Total

Example:

def calculate_total(price, quantity):
    return price * quantity

total = calculate_total(25.00, 4)

print(f"Total: {total:.2f}")

Output:

Total: 100.00

Now the function calculates.

The main program decides what to do with the result.

This is cleaner.

The function has one job:

calculate total

The main program has another job:

show result

This separation is good.

Very good.

Very professional.

Very “not spaghetti today”.

Default Parameter Values

A parameter can have a default value.

Example:

def greet_user(name="Guest"):
    print(f"Hello, {name}!")

Now you can call:

greet_user("Anna")
greet_user()

Full example:

def greet_user(name="Guest"):
    print(f"Hello, {name}!")

greet_user("Anna")
greet_user()

Output:

Hello, Anna!
Hello, Guest!

When you pass a name, Python uses it.

When you do not pass a name, Python uses "Guest".

This is useful when a value is optional.

Default values are like backup plans.

A rare thing in programming that actually sounds comforting.

Keyword Arguments

You can pass arguments by name.

Example:

def describe_product(name, price):
    print(f"{name}: {price:.2f}")

describe_product(name="Keyboard", price=70.00)

Output:

Keyboard: 70.00

This is called using keyword arguments.

It can make function calls clearer.

Especially when there are many parameters.

Example:

def create_user(name, age, city):
    print(f"{name}, {age}, {city}")

create_user(name="Anna", age=25, city="Rome")

This is more readable than:

create_user("Anna", 25, "Rome")

Both work.

Keyword arguments make the meaning clearer.

And clear code is less likely to attack you later.

Usually.

Variable Scope

Variables created inside a function exist only inside that function.

Example:

def greet():
    message = "Hello!"

greet()

print(message)

This gives an error:

NameError

Why?

Because message was created inside the function.

Outside the function, it does not exist.

This is called scope.

Scope means:

where a variable is available

A variable inside a function is local to that function.

It lives there.

It does not move out.

Very private.

Very introverted.

Local Variables

Example:

def calculate_total(price, quantity):
    total = price * quantity
    return total

result = calculate_total(10, 3)

print(result)

Output:

30

Here:

total

exists inside the function.

This works:

return total

because we are inside the function.

But this would not work:

print(total)

outside the function.

The variable total is local.

If you need the result outside the function, return it.

That is the correct way.

Do not try to steal local variables through the window.

Python locks the window.

Function with a List

Functions can receive lists.

Example:

def show_products(products):
    for product in products:
        print(f"- {product}")

items = ["Keyboard", "Mouse", "Notebook"]

show_products(items)

Output:

- Keyboard
- Mouse
- Notebook

The function receives a list.

Then it loops through the list.

This is very common.

Functions and lists work together beautifully.

A list stores many values.

A function processes them.

Very useful.

Very real.

Very “this could become a report later”.

Function That Calculates List Total

Example:

def calculate_total(prices):
    total = 0

    for price in prices:
        total += price

    return total

prices = [10.00, 25.50, 5.00]

total = calculate_total(prices)

print(f"Total: {total:.2f}")

Output:

Total: 40.50

This function works with any list of prices.

Example:

order_one = [10.00, 20.00]
order_two = [5.50, 7.25, 100.00]

print(calculate_total(order_one))
print(calculate_total(order_two))

The same function works for different data.

That is the beauty of functions.

Write once.

Reuse.

Feel slightly powerful.

Function with a Dictionary

Functions can receive dictionaries too.

Example:

def show_user(user):
    print(f"Name: {user['name']}")
    print(f"Age: {user['age']}")
    print(f"City: {user['city']}")

user = {
    "name": "Anna",
    "age": 25,
    "city": "Rome"
}

show_user(user)

Output:

Name: Anna
Age: 25
City: Rome

This is very useful.

A dictionary stores structured data.

A function displays or processes it.

Real applications do this constantly.

Users.

Products.

Orders.

Profiles.

Everything becomes easier when functions handle structured data.

Very practical.

Very backend-friendly.

Function with List of Dictionaries

Example:

def show_products(products):
    for product in products:
        print(f"{product['name']}: {product['price']:.2f}")

products = [
    {"name": "Keyboard", "price": 70.00},
    {"name": "Mouse", "price": 25.00},
    {"name": "Notebook", "price": 5.50}
]

show_products(products)

Output:

Keyboard: 70.00
Mouse: 25.00
Notebook: 5.50

This is a strong pattern.

You already know lists.

You already know dictionaries.

Now you are putting functions around them.

This is how programs become organized.

Data structures store data.

Functions work with data.

Very important idea.

Very software.

Common Mistake: Forgetting Parentheses

Wrong:

def greet():
    print("Hello!")

greet

This does not call the function.

Correct:

greet()

Parentheses call the function.

Without parentheses, you are only referring to the function.

Python says:

Yes, that function exists.

But it does not run it.

A function call needs parentheses.

Tiny circles.

Big responsibility.

Common Mistake: Forgetting the Colon

Wrong:

def greet()
    print("Hello!")

Correct:

def greet():
    print("Hello!")

Function definitions need a colon.

Python loves colons.

Conditions need colons.

Loops need colons.

Functions need colons.

Python is basically building a small colon collection.

Respect it.

Common Mistake: Wrong Indentation

Wrong:

def greet():
print("Hello!")

Correct:

def greet():
    print("Hello!")

The function body must be indented.

If the indentation is wrong, Python gives:

IndentationError

This is not Python being dramatic.

It genuinely does not know what belongs to the function.

Indentation is structure.

Again.

Always again.

Common Mistake: Using a Variable Before Return

Wrong:

def add_numbers(a, b):
    total = a + b

result = add_numbers(5, 3)

print(result)

Output:

None

Why?

Because the function does not return anything.

Correct:

def add_numbers(a, b):
    total = a + b
    return total

result = add_numbers(5, 3)

print(result)

Output:

8

If you need the value outside the function, return it.

Do not just calculate it.

A calculation trapped inside a function is like a pizza behind glass.

Looks nice.

Not useful.

Common Mistake: Code After return

When Python reaches return, the function stops.

Example:

def test():
    return "Done"
    print("This will not run")

message = test()

print(message)

Output:

Done

This line does not run:

print("This will not run")

Because it is after return.

return exits the function immediately.

Very important.

Anything after return in the same block is ignored.

Like advice after someone already closed the door.

Common Mistake: Too Many Responsibilities

Bad function:

def do_everything():
    print("Show menu")
    print("Ask user")
    print("Add product")
    print("Calculate total")
    print("Send email")

This function does too much.

Better:

def show_menu():
    print("Menu")

def add_product():
    print("Add product")

def calculate_total():
    print("Calculate total")

A good function usually does one clear thing.

Not always perfectly.

But try.

Functions should be small enough to understand.

If a function becomes huge, it may need to be split.

Like a pizza.

But with code.

Mini Program: Greeting Function

Create a file:

greeting_function.py

Write:

def greet_user(name):
    print(f"Hello, {name}!")
    print("Welcome to the program.")

user_name = input("What is your name? ")

greet_user(user_name)

Example:

What is your name? Anna

Output:

Hello, Anna!
Welcome to the program.

This program uses:

Simple.

But important.

You are no longer just writing linear code.

You are organizing behavior.

Very good.

Mini Program: Total Calculator

Create a file:

total_calculator.py

Write:

def calculate_total(price, quantity):
    return price * quantity

price = float(input("Price: "))
quantity = int(input("Quantity: "))

total = calculate_total(price, quantity)

print(f"Total: {total:.2f}")

Example:

Price: 25
Quantity: 4

Output:

Total: 100.00

This program uses:

Very practical.

Very shop-like.

Very “this may become an invoice one day”.

Careful.

Invoices attract taxes.

Mini Program: Average Function

Create a file:

average_function.py

Write:

def calculate_average(numbers):
    total = 0

    for number in numbers:
        total += number

    return total / len(numbers)

scores = []

score_count = int(input("How many scores? "))

for number in range(1, score_count + 1):
    score = float(input(f"Score {number}: "))
    scores.append(score)

average = calculate_average(scores)

print(f"Average: {average:.2f}")

Example:

How many scores? 3
Score 1: 80
Score 2: 90
Score 3: 70

Output:

Average: 80.00

This program combines:

Very strong beginner practice.

This is a real pattern.

Collect data.

Pass data to a function.

Get result.

Show result.

Clean.

Useful.

Professional enough to scare spaghetti code away.

Practice

Create a file:

practice_functions.py

Write a program that:

Example solution:

def calculate_discount(price, discount_percent):
    discount_amount = price * discount_percent / 100
    final_price = price - discount_amount
    return final_price

price = float(input("Price: "))
discount = float(input("Discount percent: "))

final_price = calculate_discount(price, discount)

print(f"Final price: {final_price:.2f}")

Example:

Price: 100
Discount percent: 20

Output:

Final price: 80.00

This is very useful.

Discounts are everywhere.

Shops use them.

Customers like them.

Developers calculate them.

Accountants verify them.

Everyone has a role.

Very organized chaos.

Mini Challenge

Create a file:

task_manager_functions.py

Your program should:

Example solution:

tasks = []

def show_menu():
    print("----- Task Manager -----")
    print("1. Add task")
    print("2. Show tasks")
    print("q. Quit")

def add_task(tasks):
    task = input("Task: ")
    tasks.append(task)
    print("Task added.")

def show_tasks(tasks):
    if len(tasks) == 0:
        print("No tasks yet.")
    else:
        print("Tasks:")

        for task in tasks:
            print(f"- {task}")

while True:
    show_menu()

    choice = input("Choose an option: ").lower()

    if choice == "1":
        add_task(tasks)
    elif choice == "2":
        show_tasks(tasks)
    elif choice == "q":
        print("Goodbye.")
        break
    else:
        print("Unknown option.")

This is a better version of the task manager.

Why?

Because the code is organized into functions.

Each function has a job:

show_menu      shows the menu
add_task       adds a task
show_tasks     shows all tasks

The main loop becomes easier to read.

This is the point of functions.

They make programs easier to organize.

Less chaos.

More structure.

Still Python.

Extra Challenge: Product Functions

Create a file:

product_functions.py

Build a program with these functions:

create_product()
show_product(product)
calculate_total(products)

Each product should be a dictionary with:

name
price
quantity

Example idea:

def create_product():
    product = {
        "name": input("Name: "),
        "price": float(input("Price: ")),
        "quantity": int(input("Quantity: "))
    }

    return product

def show_product(product):
    total = product["price"] * product["quantity"]
    print(f"{product['name']}: {product['quantity']} x {product['price']:.2f} = {total:.2f}")

def calculate_total(products):
    total = 0

    for product in products:
        total += product["price"] * product["quantity"]

    return total

products = []

product_count = int(input("How many products? "))

for number in range(1, product_count + 1):
    print(f"Product {number}")
    product = create_product()
    products.append(product)

print("----- Products -----")

for product in products:
    show_product(product)

total = calculate_total(products)

print(f"Total: {total:.2f}")

This challenge combines:

This is serious beginner Python.

Small shop logic.

Structured data.

Reusable code.

Very strong.

Very useful.

Very “you are starting to build real things”.

Beginner Checklist

When your function does not work, check:

Did I use def?
Did I add parentheses?
Did I add a colon?
Did I indent the function body?
Did I call the function?
Did I pass the correct number of arguments?
Did I spell the function name correctly?
Did I use return if I need a value back?
Am I confusing print() and return?
Is the variable local to the function?
Did I put code after return?
Does the function do too many things?

Functions are powerful.

But they introduce new mistakes.

This is normal.

At first, functions feel like extra work.

Then one day you write a program without functions and feel pain.

That is when you understand.

Growth is beautiful.

And slightly annoying.

Summary

Today you learned:

This is a huge step.

Your code can now become cleaner.

More reusable.

More organized.

Less copy-paste.

Less chaos.

Functions are one of the main tools that turn beginner scripts into real programs.

You are not just writing commands anymore.

You are creating reusable behavior.

That is serious progress.

Very Python.

Very next level.

Next Lesson

In the next lesson, we will learn files.

Files let your programs save data.

Right now, when the program ends, data disappears.

Very sad.

Very temporary.

With files, you can write data to disk and read it later.

For example:

save tasks
load tasks
save contacts
read notes
write reports

This is very important.

Because programs become much more useful when they remember things.

Memory is power.

Unless you saved the wrong file.

Then memory is drama.

Very educational drama.