IS4010: AI-Enhanced Application Development

Week 5: Functions & Error Handling

Brandon M. Greenwell

Session 1: Writing clean functions

Why use functions?

  • The most important reason is the DRY principle: don’t repeat yourself.
  • Functions allow us to break down large, complex problems into smaller, logical, and more manageable pieces.
  • This makes our code easier to read, test, and debug.
  • It also promotes reusability. You can write a function once and use it many times throughout your application.

The anatomy of a python function

  • Let’s break down the core components of a modern python function.
  • We use the def keyword, a descriptive name, parameters with type hints, a return type, and a numpy-style docstring.
def calculate_area(length: float, width: float) -> float:
    """Calculate the area of a rectangle.

    Parameters
    ------
    length : float
        The length of the rectangle.
    width : float
        The width of the rectangle.

    Returns
    -----
    float
        The calculated area of the rectangle.
    """
    return length * width

Understanding variable scope

  • Scope refers to the region of code where a variable is accessible.
  • Variables created inside a function have local scope. They only exist within that function.
  • Variables created outside of any function have global scope.
  • This is a good thing! It prevents functions from accidentally modifying variables they shouldn’t have access to.
def my_function():
    # secret_number has local scope
    secret_number = 42
    print("Inside the function, the number is", secret_number)

my_function()
# This next line would cause a NameError!
# print("Outside the function, the number is", secret_number)

AI-assisted refactoring

  • One of the most powerful uses for an AI partner is refactoring code.
  • You can give it a messy, procedural script and ask it to break it down into clean, reusable functions.
  • A good prompt: “act as a senior python developer. review this script and refactor it into clean, reusable functions. make sure each function has a specific purpose and a numpy-style docstring.”
  • This is the core idea behind our lab for this week.

Session 2: Building robust code

When things go wrong: exceptions

  • A syntax error is like bad grammar; python doesn’t even understand the code, so it won’t run.
  • A runtime error, or exception, happens while the program is running. The code is syntactically correct, but something unexpected occurred.
  • For example, you can’t divide a number by zero or open a file that doesn’t exist. These actions raise exceptions.
  • Unhandled exceptions will crash your program.

Handling exceptions with try and except

  • We can handle these errors gracefully using a try...except block.
  • The try block contains the code that might fail.
  • The except block contains the code that runs only if an error occurs in the try block.
  • It’s best practice to catch specific exceptions so you can handle different errors in different ways.
try:
    age_string = input("Please enter your age: ")
    age = int(age_string)
    print(f"Next year, you will be {age + 1}.")
except ValueError:
    print("Invalid input. Please enter a whole number.")

The else and finally clauses

  • We can add two more optional clauses to our error handling.
  • The else block runs only if the try block completes successfully (no exception was raised).
  • The finally block runs no matter what. It will always execute, whether an exception happened or not. This is perfect for cleanup code, like closing a file.
# A simplified file operation
try:
    f = open("my_data.txt")
    # ... process the file
except FileNotFoundError:
    print("Error: Could not find the file.")
else:
    print("File processed successfully.")
finally:
    print("Executing cleanup. The 'try' block is now finished.")
    # In a real app, you would close the file here: f.close()

Introducing lab 05

  • This week’s lab will have two parts, mirroring our two sessions.
  • Part 1: The refactor challenge. You will be given a messy script and use your AI partner to refactor it into clean functions.
  • Part 2: Bulletproof your code. You will take your newly refactored code and add try...except blocks to handle potential runtime errors.
  • Full instructions are in labs/lab05/README.md.