Daily Tech Brief

Top startup stories in your inbox

Subscribe Free

© 2026 rakrisi Daily

Functions - Reusable Code Blocks

Functions: The Building Blocks of Reusable Code

Welcome to the world of functions! Think of functions as recipes in a cookbook. Once you write a good recipe, you can use it over and over again.

What are Functions?

Functions are like kitchen appliances:

  • Blender: Takes ingredients, mixes them, returns smoothie
  • Microwave: Takes food and time, heats it, returns hot food
  • Dishwasher: Takes dirty dishes, washes them, returns clean dishes

Each appliance has a specific job and can be used repeatedly!

Why Use Functions?

Real-Life Benefits

  1. Reusability: Write once, use many times
  2. Organization: Break complex tasks into smaller pieces
  3. Maintainability: Fix bugs in one place
  4. Readability: Code becomes self-documenting
  5. Testing: Test small pieces individually

Code Without Functions (Bad)

# Calculate area of rectangle
length1 = 5
width1 = 3
area1 = length1 * width1
print(f"Rectangle 1 area: {area1}")

# Calculate area of another rectangle
length2 = 7
width2 = 4
area2 = length2 * width2
print(f"Rectangle 2 area: {area2}")

# Calculate area of a third rectangle
length3 = 10
width3 = 2
area3 = length3 * width3
print(f"Rectangle 3 area: {area3}")

# Lots of repeated code!

Code With Functions (Good)

def calculate_rectangle_area(length, width):
    """Calculate the area of a rectangle."""
    return length * width

# Now use the function multiple times
area1 = calculate_rectangle_area(5, 3)
print(f"Rectangle 1 area: {area1}")

area2 = calculate_rectangle_area(7, 4)
print(f"Rectangle 2 area: {area2}")

area3 = calculate_rectangle_area(10, 2)
print(f"Rectangle 3 area: {area3}")

# Much cleaner and reusable!

Defining Functions

Basic Function Structure

def function_name(parameter1, parameter2):
    """
    Optional docstring: describes what the function does.
    """
    # Function body - the code that runs
    result = parameter1 + parameter2
    return result  # Optional: what the function gives back

Real-Life Example: Coffee Maker Function

def make_coffee(coffee_type, sugar_spoons=0, milk=False):
    """
    Make a cup of coffee with specified parameters.

    Args:
        coffee_type (str): Type of coffee (espresso, latte, etc.)
        sugar_spoons (int): Number of sugar spoons (default: 0)
        milk (bool): Whether to add milk (default: False)

    Returns:
        str: Description of the prepared coffee
    """
    coffee = f"A cup of {coffee_type}"

    if sugar_spoons > 0:
        coffee += f" with {sugar_spoons} spoons of sugar"
    else:
        coffee += " (no sugar)"

    if milk:
        coffee += " and milk"
    else:
        coffee += " (black)"

    return coffee

# Use the function
my_coffee = make_coffee("espresso", sugar_spoons=2, milk=True)
print(my_coffee)  # "A cup of espresso with 2 spoons of sugar and milk"

friends_coffee = make_coffee("latte", milk=True)
print(friends_coffee)  # "A cup of latte (no sugar) and milk"

Function Parameters

Required Parameters

def greet_person(name):
    """Greet a person by name."""
    return f"Hello, {name}!"

# Must provide the name parameter
greeting = greet_person("Alice")
print(greeting)  # "Hello, Alice!"

# greet_person()  # Error: missing required argument

Default Parameters

def make_ice_cream(flavor, scoops=1, cone=True):
    """Make ice cream with specified parameters."""
    order = f"{scoops} scoop{'s' if scoops > 1 else ''} of {flavor}"

    if cone:
        order += " in a cone"
    else:
        order += " in a cup"

    return order

# Use with defaults
single_scoop = make_ice_cream("vanilla")
print(single_scoop)  # "1 scoop of vanilla in a cone"

# Override defaults
double_cup = make_ice_cream("chocolate", scoops=2, cone=False)
print(double_cup)  # "2 scoops of chocolate in a cup"

Variable Number of Arguments (*args)

def make_pizza(*toppings):
    """Make a pizza with any number of toppings."""
    if not toppings:
        return "Plain cheese pizza"

    topping_list = ", ".join(toppings)
    return f"Pizza with {topping_list}"

# Different numbers of toppings
plain_pizza = make_pizza()
print(plain_pizza)  # "Plain cheese pizza"

pepperoni_pizza = make_pizza("pepperoni")
print(pepperoni_pizza)  # "Pizza with pepperoni"

supreme_pizza = make_pizza("pepperoni", "mushrooms", "onions", "bell peppers")
print(supreme_pizza)  # "Pizza with pepperoni, mushrooms, onions, bell peppers"

Keyword Arguments (**kwargs)

def build_computer(**specs):
    """Build a computer with specified specifications."""
    computer = "Custom computer with:\n"

    for component, spec in specs.items():
        computer += f"  - {component}: {spec}\n"

    return computer.strip()

# Build different computers
gaming_pc = build_computer(
    CPU="Intel i7",
    GPU="RTX 3080",
    RAM="32GB",
    storage="1TB SSD"
)
print(gaming_pc)

office_pc = build_computer(
    CPU="Intel i5",
    RAM="16GB",
    storage="512GB SSD"
)
print(office_pc)

Return Values

Functions with Return Values

def calculate_discount(price, discount_percent):
    """Calculate discounted price."""
    discount_amount = price * (discount_percent / 100)
    final_price = price - discount_amount
    return final_price

# Use the returned value
original_price = 100
sale_price = calculate_discount(original_price, 20)
print(f"Original: ${original_price}, Sale: ${sale_price}")  # "Original: $100, Sale: $80"

Functions Without Return Values

def print_welcome_message(name):
    """Print a welcome message (no return value)."""
    print(f"Welcome to our store, {name}!")
    print("We hope you find everything you need.")

# Function returns None implicitly
result = print_welcome_message("Alice")
print(f"Function returned: {result}")  # "Function returned: None"

Multiple Return Values

def analyze_numbers(numbers):
    """Analyze a list of numbers."""
    if not numbers:
        return None, None, None

    total = sum(numbers)
    average = total / len(numbers)
    maximum = max(numbers)

    return total, average, maximum

# Unpack multiple return values
nums = [10, 20, 30, 40, 50]
total, avg, max_num = analyze_numbers(nums)

print(f"Total: {total}, Average: {avg:.2f}, Maximum: {max_num}")
# "Total: 150, Average: 30.00, Maximum: 50"

Scope and Variables

Local vs Global Variables

global_variable = "I am global"

def demonstrate_scope():
    local_variable = "I am local"
    print(f"Inside function: {global_variable}")  # Can access global
    print(f"Inside function: {local_variable}")   # Can access local

    # Modify global variable (need to declare global)
    global global_variable
    global_variable = "I was modified inside function"

demonstrate_scope()
print(f"Outside function: {global_variable}")  # Modified global
# print(local_variable)  # Error: local_variable not defined outside function

Best Practice: Avoid Global Variables

# ❌ Bad: Using global variables
total_purchases = 0

def add_purchase(amount):
    global total_purchases
    total_purchases += amount

# ✅ Good: Pass parameters and return values
def add_purchase(current_total, amount):
    return current_total + amount

# Usage
total = 0
total = add_purchase(total, 50)
total = add_purchase(total, 30)
print(f"Total purchases: ${total}")

Function Examples

Example 1: Temperature Converter

def celsius_to_fahrenheit(celsius):
    """Convert Celsius to Fahrenheit."""
    return (celsius * 9/5) + 32

def fahrenheit_to_celsius(fahrenheit):
    """Convert Fahrenheit to Celsius."""
    return (fahrenheit - 32) * 5/9

# Use the functions
temp_c = 25
temp_f = celsius_to_fahrenheit(temp_c)
print(f"{temp_c}°C = {temp_f}°F")

temp_f2 = 77
temp_c2 = fahrenheit_to_celsius(temp_f2)
print(f"{temp_f2}°F = {temp_c2:.1f}°C")

Example 2: Simple Calculator

def add(x, y):
    return x + y

def subtract(x, y):
    return x - y

def multiply(x, y):
    return x * y

def divide(x, y):
    if y == 0:
        return "Error: Division by zero!"
    return x / y

# Calculator function
def calculator(operation, x, y):
    """Perform calculation based on operation."""
    if operation == "add":
        return add(x, y)
    elif operation == "subtract":
        return subtract(x, y)
    elif operation == "multiply":
        return multiply(x, y)
    elif operation == "divide":
        return divide(x, y)
    else:
        return "Error: Unknown operation!"

# Use the calculator
result1 = calculator("add", 10, 5)
print(f"10 + 5 = {result1}")

result2 = calculator("divide", 10, 0)
print(result2)  # "Error: Division by zero!"

Example 3: Password Validator

def validate_password(password):
    """
    Validate password strength.
    Returns (is_valid, message)
    """
    if len(password) < 8:
        return False, "Password must be at least 8 characters long"

    has_upper = any(char.isupper() for char in password)
    has_lower = any(char.islower() for char in password)
    has_digit = any(char.isdigit() for char in password)

    if not has_upper:
        return False, "Password must contain at least one uppercase letter"
    if not has_lower:
        return False, "Password must contain at least one lowercase letter"
    if not has_digit:
        return False, "Password must contain at least one digit"

    return True, "Password is strong!"

# Test passwords
passwords = ["weak", "Password", "password123", "Password123"]

for pwd in passwords:
    is_valid, message = validate_password(pwd)
    status = "" if is_valid else ""
    print(f"{status} {pwd}: {message}")

Lambda Functions (Anonymous Functions)

Simple Lambda Functions

# Regular function
def square(x):
    return x ** 2

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

print(square(5))          # 25
print(square_lambda(5))   # 25

Lambda with Multiple Parameters

# Regular function
def add(x, y):
    return x + y

# Lambda equivalent
add_lambda = lambda x, y: x + y

print(add(3, 4))          # 7
print(add_lambda(3, 4))   # 7

Common Lambda Use Cases

# Sort list of tuples by second element
students = [("Alice", 85), ("Bob", 92), ("Charlie", 78)]
students.sort(key=lambda student: student[1])  # Sort by grade
print(students)  # [('Charlie', 78), ('Alice', 85), ('Bob', 92)]

# Filter even numbers
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers)  # [2, 4, 6, 8, 10]

# Transform list elements
names = ["alice", "bob", "charlie"]
capitalized = list(map(lambda name: name.capitalize(), names))
print(capitalized)  # ['Alice', 'Bob', 'Charlie']

Function Best Practices

1. Single Responsibility Principle

# ❌ Bad: Function does too many things
def process_user_data(data):
    # Validate data
    # Save to database
    # Send email
    # Log activity
    pass

# ✅ Good: Each function has one responsibility
def validate_user_data(data):
    pass

def save_user_to_database(user):
    pass

def send_welcome_email(user):
    pass

def log_user_activity(user, action):
    pass

2. Descriptive Names

# ❌ Bad names
def f(x, y):          # What does f do?
    return x * y

def calc(a, b, c):    # What calculation?
    return (a + b) * c

# ✅ Good names
def calculate_rectangle_area(length, width):
    return length * width

def calculate_discounted_price(original_price, discount_rate):
    return original_price * (1 - discount_rate)

3. Docstrings

# ❌ No documentation
def calculate_tax(amount):
    return amount * 0.08

# ✅ With docstring
def calculate_tax(amount, tax_rate=0.08):
    """
    Calculate tax amount for a given amount.

    Args:
        amount (float): The amount to calculate tax for
        tax_rate (float): Tax rate as decimal (default: 0.08 for 8%)

    Returns:
        float: The calculated tax amount

    Examples:
        >>> calculate_tax(100)
        8.0
        >>> calculate_tax(100, 0.10)
        10.0
    """
    return amount * tax_rate

4. Error Handling

# ❌ No error handling
def divide_numbers(x, y):
    return x / y

# result = divide_numbers(10, 0)  # Crash!

# ✅ With error handling
def safe_divide(x, y):
    """
    Safely divide two numbers.

    Args:
        x (float): Numerator
        y (float): Denominator

    Returns:
        float or None: Result of division, or None if division by zero
    """
    try:
        return x / y
    except ZeroDivisionError:
        print("Error: Cannot divide by zero!")
        return None

result = safe_divide(10, 0)  # Returns None, no crash

Practice Exercises

Exercise 1: Unit Converter

Create functions to convert between different units:

  • Celsius ↔ Fahrenheit
  • Kilometers ↔ Miles
  • Kilograms ↔ Pounds

Exercise 2: Shopping Cart Functions

Create functions for a shopping cart:

  • Add item to cart
  • Remove item from cart
  • Calculate total price
  • Apply discount

Exercise 3: Text Processing Functions

Create functions for text processing:

  • Count words in a string
  • Check if string is palindrome
  • Capitalize first letter of each word
  • Remove punctuation

Exercise 4: Math Functions

Create mathematical functions:

  • Factorial calculation
  • Check if number is prime
  • Generate Fibonacci sequence
  • Calculate compound interest

Exercise 5: File Operations (Preview)

Create functions for file operations:

  • Read text file
  • Write to text file
  • Count lines in file
  • Search for word in file

Summary

Functions are the building blocks of organized, reusable code:

  • Define functions with def function_name(parameters):
  • Parameters: Required, default, *args, **kwargs
  • Return values: Use return to send results back
  • Scope: Local variables are only accessible inside functions
  • Lambda functions: Anonymous functions for simple operations

Benefits of functions:

  • Reusability: Write once, use many times
  • Organization: Break complex problems into smaller pieces
  • Maintainability: Easier to debug and update
  • Readability: Self-documenting code
  • Testing: Test individual components

Next: Data Structures - organizing data efficiently! 📊