Writing Functions

Topics: functions

Functions are the building blocks of well-organized code. They let you write logic once and reuse it across multiple scenarios — an essential skill when automating tasks like calculating BMI, summarizing lab results, or cleaning patient datasets.

Function Basics Review

Let’s say we want to create a function that greets a patient when their name is entered into a system.

def greet(name):
    """A simple function that greets someone."""
    return f"Hello, {name}! Welcome to your appointment."

Call the function:

message = greet("Dr. Reyes")
print(message)                     # Output: Hello, Dr. Reyes! Welcome to your appointment.

Advanced Function Features

Default Parameters

Let’s define a function that creates a basic patient profile — similar to what you’d store in an electronic medical record (EMR).

def create_profile(name, age, city="Davao", diagnosis="Not yet diagnosed"):
    """Create a patient profile with default values."""
    profile = {
        "name": name,
        "age": age,
        "city": city,
        "diagnosis": diagnosis
    }
    return profile

Run the function using (1) default parameters and (2) custom parameters:

patient1 = create_profile("Ana Santos", 35)
patient2 = create_profile("Miguel Cruz", 58, "Davao", "Hypertension")

print(patient1)  # city and diagnosis use defaults
print(patient2)  # all parameters specified
Keyword Arguments

Here’s a fun analogy: imagine writing a function that orders medical supplies (instead of pizza).

def order_supplies(quantity, *items, **details):
    """Order medical supplies with flexible arguments."""
    print(f"Order quantity: {quantity}")
    print(f"Items: {', '.join(items)}")

    for key, value in details.items():
        print(f"{key}: {value}")

Call the function:

order_supplies(3, "syringes", "bandages",
               urgent=True, delivery="Next-day")
Variable-Length Arguments

You can also design flexible functions that handle any number of lab results or patient details.

Example 1: Calculate average blood glucose readings:

def calculate_average(*values):
    """Calculate average of any number of readings."""
    if not values:
        return 0
    return sum(values) / len(values)

Example 2: Create a patient record with flexible fields:

def create_patient_record(name, **info):
    """Create a patient record with flexible information."""
    record = {"name": name}
    record.update(info)
    return record

Use the functions:

avg_glucose = calculate_average(92, 110, 87, 105)
print(f"Average Glucose: {avg_glucose:.1f} mg/dL")

patient = create_patient_record(
    "Maria Dela Cruz",
    age=47,
    condition="Diabetes",
    medications=["Metformin", "Insulin"],
    last_visit="2025-09-10"
)
print(patient)
Lambda Functions (Anonymous Functions)

Lambda functions are compact, one-line functions useful for quick calculations or filtering data.

For instance, you could quickly identify patients with elevated BMI values.

# Regular function
def bmi(weight, height):
    return weight / (height ** 2)

# Lambda equivalent
bmi_lambda = lambda weight, height: weight / (height ** 2)

print(bmi_lambda(70, 1.75))  # Output: 22.86

Filtering a list of patients:

patients = [
    {"name": "Ana", "bmi": 22.5},
    {"name": "Ben", "bmi": 29.8},
    {"name": "Clara", "bmi": 18.9}
]

# Get only overweight patients (BMI ≥ 25)
overweight = list(filter(lambda p: p["bmi"] >= 25, patients))
print(overweight)

What are its advantages of a lambda function.

  • Inline definition: You can define a function in a single line without naming it
  • Saves space: Ideal for short, throwaway functions used once or in a small scope
  • Great for Testing and Prototyping

What are the disadvantages?

  • they can hurt readability if overused or used for complex logic
  • if your function spans multiple operations or needs documentation, a named def function is usually better

Let’s see another example:

# Lambda equivalent
square_lambda = lambda x: x ** 2

# Common use with built-in functions
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
print(squared)  # [1, 4, 9, 16, 25]

# Filtering with lambda
students = [
    {"name": "Alice", "grade": 85},
    {"name": "Bob", "grade": 92},
    {"name": "Charlie", "grade": 78}
]

high_performers = list(filter(lambda s: s["grade"] >= 85, students))
print(high_performers)