DEV Community

Cover image for Python Functions: Stop Repeating Yourself, Let Functions Do the Work
Okall Omondi
Okall Omondi

Posted on

Python Functions: Stop Repeating Yourself, Let Functions Do the Work

Have you ever been in a situation where you have to do the same task repetitively?
It can be tiresome right?
We often find ourselves in similar situations when writing code. For example, when you are required to calculate a value three different times in the same program. You have the option of copying and pasting twenty lines of code, modifying a single variable name, and crossing your fingers that you didn't introduce a typo, or... use loops and functions.

Check my article on How Python Loops Actually Work: A Hands-On Guide with Real Projects

A function is simply a packaged block of reusable code designed to perform a single task. Instead of rewriting instructions over and over, you write them once, give that package a name, and run it whenever you need it.


Defining and Calling a Function

Creating a function in Python requires the def keyword, followed by a name, parentheses, and a colon. The indented lines underneath form the body of the function.

def greet():
    print("Welcome back!")
Enter fullscreen mode Exit fullscreen mode

Defining a function does not run it. It only teaches Python what the function does. To execute that logic, you must call it by writing its name followed by parentheses:

greet()  # Output: Welcome back!
Enter fullscreen mode Exit fullscreen mode

If you leave off the parentheses, Python will not run the code; it will simply tell you that the name refers to a function object in memory.


Inputs: Parameters vs. Arguments

Most functions need data to do meaningful work. We pass data into functions using parameters and arguments. People often use these two terms interchangeably, but there is a clear distinction:

  • Parameters are the placeholder variable names listed in the function definition (subtotal and tax_rate in the program below).
  • Arguments are the actual values passed into the function when you call it (100, 0.20 in the program below).
def calculate_tax(subtotal, tax_rate=0.16):
    total = subtotal * (1 + tax_rate)
    print(f"Total with tax: ${total:.2f}")

calculate_tax(100)        # Uses the default tax_rate of 0.16
calculate_tax(100, 0.20)  # Overrides tax_rate with 0.20
Enter fullscreen mode Exit fullscreen mode

Notice tax_rate=0.16. That is a default parameter. It allows the caller to omit that argument unless they specifically need a different rate.


Returning Values vs. Printing

Beginners often confuse print() with return.

A print() statement merely displays text in your terminal for human eyes. It does not hand data back to your program. The return statement, on the other hand, ends the function and sends data back to the line of code that called it, letting you store that output in a variable.

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

result = add(4, 6)
# result now holds the integer 10, which we can use anywhere else
print(result * 2)  # Output: 20
Enter fullscreen mode Exit fullscreen mode

If a function finishes without encountering a return statement, Python silently returns None.


Variable Scope: Local vs. Global

Scope dictates where a variable can be seen and used.

Variables created inside a function are local. They exist only while that function is running and disappear the moment it finishes.

def set_discount():
    discount = 15  # Local variable
    return discount

set_discount()
# print(discount)  # Raises NameError: name 'discount' is not defined
Enter fullscreen mode Exit fullscreen mode

Variables created outside functions in your main script are global. While functions can read global variables, modifying them inside a function requires extra care.

As a best practice, avoid relying on global state inside functions. Pass what the function needs through arguments, and get results back using return. This keeps your code predictable and easy to debug.


Practical Example: A Simple Order Processor

Here is a realistic pattern showing how small, focused functions work together to process an e-commerce order:

def calculate_subtotal(prices):
    return sum(prices)

def apply_coupon(amount, code):
    if code == "SAVE10":
        return amount * 0.90
    return amount

def finalize_order(cart_prices, coupon_code=""):
    subtotal = calculate_subtotal(cart_prices)
    discounted = apply_coupon(subtotal, coupon_code)
    final_total = round(discounted, 2)

    return {
        "items_count": len(cart_prices),
        "final_total": final_total
    }

# Running the workflow
cart = [1000, 5000, 2500]
order_summary = finalize_order(cart, "SAVE10")

print(f"Items: {order_summary['items_count']}")
print(f"Total Due: Ksh. {order_summary['final_total']}")
Enter fullscreen mode Exit fullscreen mode

Notice how finalize_order does not calculate the sum or discount itself. It coordinates smaller helper functions. If tax or coupon logic changes later, you update only one isolated block of code.


Common Mistakes to Watch Out For

  1. Modifying a mutable default argument: Writing def add_item(item, basket=[]) leads to strange bugs. Python creates that list once when the function is defined, meaning the same list persists across every call. Use basket=None instead and initialize an empty list inside.
  2. Forgetting to return: If your calculations vanish and variables print as None, check whether you ended your function with return.
  3. Writing functions that do too much: If a single function fetches data, validates it, formats it, and prints it, break it up. Aim for functions that do one thing well.

Next Steps

Functions turn scripts into clean, modular programs. The easiest way to get comfortable with them is to take a script you have already written, identify sections where you repeated logic, and extract those lines into their own functions. Once you can pass arguments in and return values out, larger Python projects become significantly easier to reason about and maintain.

Top comments (0)