Blog Post #112: Part 4 Recap & Project: Building a Modular Calculator

Welcome to the final post of Part 4, where we’ve learned the essential skill of organizing code with functions and modules. By embracing the DRY principle, you now have the tools to write code that is clean, reusable, and far easier to maintain.

To celebrate and solidify these concepts, we will first briefly recap the core ideas of functions and modularity. Then, we’ll put everything into practice by refactoring the simple calculator we made in Post #14 into a professional, modular application.

Part 4 Recap: Functions and Modularity

In this section, we moved from writing simple scripts to building organized programs.

  • The “Why” and “How”: We started with the “Don’t Repeat Yourself” (DRY) principle (Post #83) and learned the basic syntax for defining (def) and calling functions (Post #84).
  • Data Flow: We explored how to pass data into functions using parameters and arguments (Posts #86 Post #87 Post #88 Post #89) and how to get data out using the return statement (Posts #91 Post #92 Post #93).
  • Scope: We demystified where variables live with the concepts of local and global scope, culminating in the LEGB rule for variable lookup (Posts #94 Post#95 Post #96 Post #97 Post #98).
  • Professional Practices: We touched on professional habits like writing docstrings (Post #99) and using type hints (Post #100), and learned how to create flexible functions with *args and **kwargs (Posts #101 Post #102 Post #103).
  • Modularity: Finally, we learned how to break our code into separate files called modules (Post #109), how to import them (Post #110), and how to make our files both importable and runnable using if __name__ == '__main__' (Post #111).

Project: The Modular Calculator

Our goal is to build a calculator application that properly separates its concerns. We will have one file for our core math logic (the module) and another for handling the user interface (the main script).

Make sure you create these two files in the same directory.

Step 1: Create the Functions Module

First, create a file named calculator_functions.py. This file will contain only our reusable math functions, each with a clear docstring. It will act as our “logic” layer.

calculator_functions.py:

def add(a, b):
    """Returns the sum of two numbers."""
    return a + b

def subtract(a, b):
    """Returns the difference of two numbers."""
    return a - b

def multiply(a, b):
    """Returns the product of two numbers."""
    return a * b

def divide(a, b):
    """Returns the division of two numbers, handling division by zero."""
    if b == 0:
        return "Error: Cannot divide by zero."
    return a / b

Step 2: Create the Main Application Script

Next, create a second file named main.py. This will be the user-facing part of our application—the “presentation” layer. It will import our other file and handle all the print and input statements.

main.py:

# Import the entire module we just created
import calculator_functions

def run_calculator():
    """Runs the main calculator loop."""
    while True:
        print("\n--- Modular Calculator Menu ---")
        print("1. Add")
        print("2. Subtract")
        print("3. Multiply")
        print("4. Divide")
        print("5. Exit")
        
        choice = input("Enter your choice (1-5): ")

        if choice == '5':
            print("Goodbye!")
            break

        if choice in ['1', '2', '3', '4']:
            try:
                num1 = float(input("Enter the first number: "))
                num2 = float(input("Enter the second number: "))
            except ValueError:
                print("Invalid input. Please enter numbers only.")
                continue

            if choice == '1':
                result = calculator_functions.add(num1, num2)
                print(f"Result: {num1} + {num2} = {result}")
            elif choice == '2':
                result = calculator_functions.subtract(num1, num2)
                print(f"Result: {num1} - {num2} = {result}")
            elif choice == '3':
                result = calculator_functions.multiply(num1, num2)
                print(f"Result: {num1} * {num2} = {result}")
            elif choice == '4':
                result = calculator_functions.divide(num1, num2)
                print(f"Result: {num1} / {num2} = {result}")
        else:
            print("Invalid choice. Please enter a number from 1 to 5.")

# This ensures our main logic only runs when this file is executed directly
if __name__ == "__main__":
    run_calculator()

Congratulations and What’s Next for Part 5

Excellent work! You have successfully built a modular application that separates logic from presentation. This is a huge step toward writing professional-grade Python. You now understand how to structure larger projects using functions and modules.

In Parts 1-4, we’ve focused on the “correct” or standard way to write Python. But what makes code feel truly elegant and “Pythonic”? Part 5 is all about style and advanced, idiomatic techniques that make your code more efficient and beautiful.

In Part 5: The Pythonic Way, we will start by exploring what this term even means. We’ll introduce the “Zen of Python” and begin our journey to writing not just code that works, but code that is a pleasure to read.

Author

Debjeet Bhowmik

Experienced Cloud & DevOps Engineer with hands-on experience in AWS, GCP, Terraform, Ansible, ELK, Docker, Git, GitLab, Python, PowerShell, Shell, and theoretical knowledge on Azure, Kubernetes & Jenkins. In my free time, I write blogs on ckdbtech.com

Leave a Comment