Teacher's Guide

Chapter 7: Creating your own Functions

Teaching Objectives

By the end of this chapter, students should:

  • Understand what functions are and why they are useful
  • Know how to define and call functions in Python
  • Learn about parameters, arguments, and return values
  • Understand variable scope within functions
  • Be able to create and use functions to organize code

Preparation

Before teaching this chapter, ensure:

  • Students understand basic Python syntax, variables, and control flow
  • You have prepared simple examples that demonstrate the purpose of functions
  • Your teaching environment allows for interactive coding demonstrations
  • Students have access to computers with Python installed

Lesson Overview

1. Introduction to Functions (15 minutes)

Start by explaining what functions are:

  • Functions are reusable blocks of code that perform a specific task
  • They help organize code and avoid repetition
  • Functions allow us to break down complex problems into smaller, manageable parts

Basic function anatomy:

# Basic function definition
def say_hello():
    print("Hello, world!")

# Function call
say_hello()

Teaching points:

  • def keyword is used to define a function
  • Function names follow the same rules as variable names (lowercase, underscores)
  • Parentheses () after the function name
  • Colon : at the end of the function header
  • Indented code block for the function body
  • Call the function by using its name followed by parentheses

2. Functions with Parameters (20 minutes)

Explain how to make functions more flexible with parameters:

# Function with a parameter
def say_hello_to(name):
    print(f"Hello, {name}!")

# Call with different arguments
say_hello_to("Alice")
say_hello_to("Bob")
say_hello_to("Charlie")

Multiple parameters:

# Function with multiple parameters
def describe_pet(animal_type, pet_name):
    print(f"I have a {animal_type} named {pet_name}.")

# Call with positional arguments
describe_pet("dog", "Buddy")
describe_pet("cat", "Whiskers")

# Call with keyword arguments
describe_pet(animal_type="hamster", pet_name="Harry")
describe_pet(pet_name="Polly", animal_type="parrot")

Default parameter values:

# Function with default parameter value
def greet(name, greeting="Hello"):
    print(f"{greeting}, {name}!")

# Call with and without the optional argument
greet("David")                   # Uses default greeting
greet("Emma", "Good morning")    # Overrides default greeting

Teaching points:

  • Parameters are variables that are defined in the function definition
  • Arguments are the values passed to the function when it's called
  • Positional arguments must be in the correct order
  • Keyword arguments can be in any order
  • Default values provide fallback values for parameters
  • Parameters with default values must come after parameters without defaults

3. Return Values (20 minutes)

Explain how functions can provide results:

# Function that returns a value
def add_numbers(a, b):
    return a + b

# Store the return value
sum_result = add_numbers(5, 3)
print(f"The sum is: {sum_result}")

# Use the return value directly
print(f"10 + 20 = {add_numbers(10, 20)}")

Multiple return values:

# Function that returns multiple values
def get_dimensions():
    length = 10
    width = 5
    height = 3
    return length, width, height

# Unpack the returned values
l, w, h = get_dimensions()
print(f"Length: {l}, Width: {w}, Height: {h}")

# Or get them as a tuple
dimensions = get_dimensions()
print(f"Dimensions: {dimensions}")
print(f"Volume: {dimensions[0] * dimensions[1] * dimensions[2]}")

Returning early:

# Function with early return
def is_even(number):
    if number % 2 == 0:
        return True
    return False

# Or simply:
def is_even_simplified(number):
    return number % 2 == 0

print(f"Is 4 even? {is_even(4)}")
print(f"Is 7 even? {is_even(7)}")

Teaching points:

  • The return statement sends a value back to the caller
  • A function without a return statement returns None
  • Functions can return multiple values (as a tuple)
  • You can unpack returned values into separate variables
  • return immediately exits the function
  • Return values can be used in expressions or stored in variables

4. Variable Scope (15 minutes)

Explain how variables work inside functions:

# Global and local variables
name = "Global Name"  # Global variable

def print_name():
    name = "Local Name"  # Local variable
    print(f"Inside function: {name}")

print_name()
print(f"Outside function: {name}")

Using global variables:

count = 0  # Global variable

def increment_count():
    global count  # Declare we want to use the global variable
    count += 1
    print(f"Count is now: {count}")

increment_count()
increment_count()
increment_count()

Parameter variables:

def modify_value(x):
    x += 10
    print(f"Inside function: x = {x}")

y = 5
print(f"Before function call: y = {y}")
modify_value(y)
print(f"After function call: y = {y}")  # y remains unchanged

Teaching points:

  • Local variables only exist inside the function
  • Global variables exist outside functions and can be accessed from anywhere
  • Use the global keyword to modify global variables inside functions
  • Function parameters are local variables
  • For immutable types (numbers, strings), function calls don't affect the original variable
  • Avoid overusing global variables as they can make code harder to understand

5. Function Best Practices (15 minutes)

Discuss guidelines for writing good functions:

# Bad function example
def do_stuff(x, y):
    result = x * 2
    print(f"Doubled: {result}")
    result = result + y
    return result

# Better function example
def calculate_result(x, y):
    """
    Calculate a result by doubling x and adding y.
    
    Args:
        x: The number to double
        y: The number to add
    
    Returns:
        The final calculated value
    """
    doubled_x = x * 2
    final_result = doubled_x + y
    return final_result

# Using the better function
result = calculate_result(5, 3)
print(f"Result: {result}")

Teaching points:

  • Use descriptive function names (verb + noun is often good)
  • Keep functions small and focused on one task
  • Use docstrings to document what the function does
  • Avoid side effects (like printing inside calculation functions)
  • Return values rather than modifying global state
  • Aim for functions that are easy to test and reuse

6. Practical Examples (20 minutes)

Walk through some useful function examples:

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

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

converted_back = fahrenheit_to_celsius(temp_f)
print(f"{temp_f}°F is {converted_back}°C")

Simple calculator:

def add(a, b):
    return a + b

def subtract(a, b):
    return a - b

def multiply(a, b):
    return a * b

def divide(a, b):
    if b == 0:
        return "Error: Division by zero"
    return a / b

# Use the calculator functions
num1 = 10
num2 = 5

print(f"{num1} + {num2} = {add(num1, num2)}")
print(f"{num1} - {num2} = {subtract(num1, num2)}")
print(f"{num1} * {num2} = {multiply(num1, num2)}")
print(f"{num1} / {num2} = {divide(num1, num2)}")
print(f"{num1} / 0 = {divide(num1, 0)}")

Game helper functions:

import random

def roll_dice(sides=6):
    """Roll a dice with the given number of sides."""
    return random.randint(1, sides)

def get_user_choice(options):
    """Get a valid choice from a user."""
    while True:
        print("Please choose an option:")
        for i, option in enumerate(options, 1):
            print(f"{i}. {option}")
            
        try:
            choice = int(input("Enter your choice (number): "))
            if 1 <= choice <= len(options):
                return options[choice - 1]
            else:
                print("Invalid choice. Try again.")
        except ValueError:
            print("Please enter a number.")

# Test the dice function
print(f"Rolling a 6-sided dice: {roll_dice()}")
print(f"Rolling a 20-sided dice: {roll_dice(20)}")

# Test the choice function
# fruits = ["apple", "banana", "cherry", "date"]
# chosen = get_user_choice(fruits)
# print(f"You chose: {chosen}")

7. Guided Practice (20 minutes)

Have students create these functions:

  1. Greeting function:

    # Create a function that takes a person's name and time of day
    # and returns an appropriate greeting
    # Example: greeting("Alice", "morning") → "Good morning, Alice!"
    
    def greeting(name, time_of_day):
        return f"Good {time_of_day}, {name}!"
    
    # Test the function
    print(greeting("Alice", "morning"))
    print(greeting("Bob", "afternoon"))
    print(greeting("Charlie", "evening"))
    
  2. Area calculator:

    # Create functions to calculate area of different shapes
    
    def rectangle_area(length, width):
        return length * width
    
    def circle_area(radius):
        return 3.14159 * radius ** 2
    
    def triangle_area(base, height):
        return 0.5 * base * height
    
    # Test the functions
    print(f"Area of rectangle (4×5): {rectangle_area(4, 5)}")
    print(f"Area of circle (radius 3): {circle_area(3)}")
    print(f"Area of triangle (base 6, height 8): {triangle_area(6, 8)}")
    
  3. Text analyzer:

    # Create functions to analyze text
    
    def count_words(text):
        words = text.split()
        return len(words)
    
    def count_letters(text):
        return len([char for char in text if char.isalpha()])
    
    def is_palindrome(text):
        # Remove spaces and convert to lowercase
        clean_text = ''.join(text.lower().split())
        return clean_text == clean_text[::-1]
    
    # Test the functions
    sample_text = "Python functions are powerful!"
    print(f"Words: {count_words(sample_text)}")
    print(f"Letters: {count_letters(sample_text)}")
    
    palindrome1 = "racecar"
    palindrome2 = "A man a plan a canal Panama"
    print(f"Is '{palindrome1}' a palindrome? {is_palindrome(palindrome1)}")
    print(f"Is '{palindrome2}' a palindrome? {is_palindrome(palindrome2)}")
    

8. Challenge Activities (15 minutes)

For more advanced students:

  1. Password validator:

    # Create a function that checks if a password is strong enough
    
    def is_strong_password(password):
        """
        Check if a password is strong based on these rules:
        - At least 8 characters long
        - Contains at least one uppercase letter
        - Contains at least one lowercase letter
        - Contains at least one digit
        """
        if len(password) < 8:
            return False
            
        has_upper = False
        has_lower = False
        has_digit = False
        
        for char in password:
            if char.isupper():
                has_upper = True
            elif char.islower():
                has_lower = True
            elif char.isdigit():
                has_digit = True
                
        return has_upper and has_lower and has_digit
    
    # Test the function
    passwords = ["abc123", "PASSWORD123", "password", "Pass123", "SecretPass123"]
    for pwd in passwords:
        if is_strong_password(pwd):
            print(f"'{pwd}' is a strong password")
        else:
            print(f"'{pwd}' is NOT a strong password")
    
  2. Number functions:

    # Create functions to work with numbers
    
    def is_prime(num):
        """Check if a number is prime."""
        if num <= 1:
            return False
            
        for i in range(2, int(num ** 0.5) + 1):
            if num % i == 0:
                return False
                
        return True
    
    def get_factors(num):
        """Get all factors of a number."""
        factors = []
        for i in range(1, num + 1):
            if num % i == 0:
                factors.append(i)
        return factors
    
    def fibonacci(n):
        """Get the nth Fibonacci number."""
        if n <= 0:
            return "Input must be positive"
        elif n == 1:
            return 0
        elif n == 2:
            return 1
            
        a, b = 0, 1
        for _ in range(3, n + 1):
            a, b = b, a + b
            
        return b
    
    # Test the functions
    for num in range(10, 20):
        if is_prime(num):
            print(f"{num} is prime")
    
    print(f"Factors of 24: {get_factors(24)}")
    
    for i in range(1, 11):
        print(f"Fibonacci {i}: {fibonacci(i)}")
    

9. Review and Discussion (10 minutes)

  • Review the key concepts covered
  • Ask students to explain in their own words:
    • What is a function and why is it useful?
    • What are parameters and arguments?
    • What does the return statement do?
    • What is variable scope?

Common Challenges and Solutions

  • Understanding scope: Students may struggle with variable scope. Draw diagrams to illustrate where variables exist.
  • Confusing parameters and arguments: Be consistent in your terminology and remind students of the difference.
  • Forgetting return values: Remind students that print() is not the same as return.
  • Indentation errors: Make sure students properly indent function bodies.

Extension Activities

For students who finish early:

  • Have them create a simple text-based game using functions
  • Challenge them to refactor existing code to use functions
  • Ask them to create a library of utility functions they can reuse

Assessment

Look for these indicators of understanding:

  • Students can define and call functions correctly
  • They can use parameters appropriately
  • They understand and use return values
  • They can write functions that solve specific problems

Resources

Chapter 7: Creating your own Functions | Teacher's Guide