⚙️ Writing Functions

Functions are reusable blocks of code that perform specific tasks. They help organize your code, reduce repetition, and make programs easier to understand and maintain.

# Simple function
def greet(name):
    return f"Hello, {name}!"

# Function with multiple parameters
def add_numbers(a, b):
    result = a + b
    return result

# Using functions
message = greet("Alice")
sum_result = add_numbers(5, 3)

print(message)      # Hello, Alice!
print(sum_result)   # 8

🎯 Basic Function Structure

Every function has a name, parameters, and a body that contains the code to execute.

Simple Functions

# Function with no parameters
def say_hello():
    return "Hello, World!"

# Function with one parameter
def square(number):
    return number * number

# Function with multiple parameters
def full_name(first, last):
    return f"{first} {last}"

# Test the functions
greeting = say_hello()
squared = square(4)
name = full_name("John", "Doe")

print(greeting)  # Hello, World!
print(squared)   # 16
print(name)      # John Doe

Functions with Default Parameters

# Default parameter values
def greet_user(name, greeting="Hello"):
    return f"{greeting}, {name}!"

def calculate_price(amount, tax_rate=0.08):
    tax = amount * tax_rate
    total = amount + tax
    return total

# Using default parameters
msg1 = greet_user("Alice")           # Uses default greeting
msg2 = greet_user("Bob", "Hi")       # Custom greeting

price1 = calculate_price(100)        # Uses default tax rate
price2 = calculate_price(100, 0.1)   # Custom tax rate

print(msg1)    # Hello, Alice!
print(msg2)    # Hi, Bob!
print(price1)  # 108.0
print(price2)  # 110.0

Functions that Return Multiple Values

# Return multiple values as tuple
def get_name_parts(full_name):
    parts = full_name.split()
    first = parts[0]
    last = parts[-1]
    return first, last

def calculate_stats(numbers):
    total = sum(numbers)
    average = total / len(numbers)
    minimum = min(numbers)
    maximum = max(numbers)
    return total, average, minimum, maximum

# Unpack returned values
first, last = get_name_parts("Alice Johnson")
total, avg, min_val, max_val = calculate_stats([1, 2, 3, 4, 5])

print(f"First: {first}, Last: {last}")
print(f"Total: {total}, Average: {avg}")

📋 Function Types Reference

TypePurposeExample
No parametersFixed behaviordef get_timestamp():
With parametersVariable behaviordef greet(name):
Default parametersOptional inputsdef func(x, y=10):
Return valueProduce outputreturn result
No returnPerform actionprint("done")

🔧 Function Documentation

Adding Docstrings

def calculate_area(length, width):
    """
    Calculate the area of a rectangle.
    
    Args:
        length (float): The length of the rectangle
        width (float): The width of the rectangle
    
    Returns:
        float: The area of the rectangle
    """
    return length * width

def format_currency(amount, currency="USD"):
    """Format amount as currency string."""
    return f"{amount:.2f} {currency}"

# Help function shows docstring
help(calculate_area)

# Use the functions
area = calculate_area(5, 3)
price = format_currency(29.99)

print(f"Area: {area}")
print(f"Price: {price}")

Function with Input Validation

def divide_numbers(a, b):
    """Safely divide two numbers."""
    if b == 0:
        return "Error: Cannot divide by zero"
    return a / b

def get_grade(score):
    """Convert numeric score to letter grade."""
    if score >= 90:
        return "A"
    elif score >= 80:
        return "B"
    elif score >= 70:
        return "C"
    elif score >= 60:
        return "D"
    else:
        return "F"

# Test functions
result1 = divide_numbers(10, 2)    # 5.0
result2 = divide_numbers(10, 0)    # Error message

grade1 = get_grade(95)   # A
grade2 = get_grade(75)   # C

print(f"Division: {result1}")
print(f"Grade: {grade1}")

Functions with Lists and Dictionaries

def process_scores(scores):
    """Process a list of test scores."""
    if not scores:
        return "No scores provided"
    
    average = sum(scores) / len(scores)
    highest = max(scores)
    lowest = min(scores)
    
    return {
        "average": average,
        "highest": highest,
        "lowest": lowest,
        "count": len(scores)
    }

def create_person(name, age, city="Unknown"):
    """Create a person dictionary."""
    return {
        "name": name,
        "age": age,
        "city": city
    }

# Test functions
test_scores = [85, 92, 78, 96, 83]
stats = process_scores(test_scores)

person = create_person("Alice", 30, "New York")

print(f"Score stats: {stats}")
print(f"Person: {person}")

📊 Function Best Practices

PracticeGood ExampleAvoid
Clear namescalculate_total()calc()
Single purposeOne task per functionMultiple unrelated tasks
Return valuesreturn resultOnly print statements
Document functionsAdd docstringsNo documentation
Handle errorsCheck inputsAssume inputs are valid

🎯 Key Takeaways

🚀 What's Next?

Learn how to make your functions more flexible with *args and **kwargs for variable arguments.

Continue to: Use *args and **kwargs

Was this helpful?

😔Poor
🙁Fair
😊Good
😄Great
🤩Excellent