Python Programming · Grade 8 · Chapter 4
Functions & Variable Scope
Building modular, reusable Python programs and understanding LEGB variable scope resolution rules.
Software Engineering Case Study
10,000 Lines of Spaghetti Code
A gaming company wrote a 10,000-line script where every player calculation was copy-pasted 50 times. Changing a single rule took 3 weeks and introduced 14 new bugs!
Solution: Functions allow packaging logic into named, self-contained, repeatable modules!
Lesson Objectives
What We Will Master Today
- Define functions using `def`, parameters, keyword arguments, and docstrings.
- Understand the critical difference between `return` values and `print()` output.
- Trace variable lifetimes and scope boundaries (Local vs Global).
- Apply the LEGB Scope Rule (Local, Enclosing, Global, Built-in) to debug code.
Prior Knowledge Connection
Monolithic vs. Modular Architecture
Monolithic Script
Single long file with repeated code blocks, global state mutations, and hard-to-test logic.
Modular Function Architecture
Small, isolated functions with clear inputs and explicit return outputs. Highly reusable!
Core Concept 1
Anatomy of a Python Function
A function is defined using the def keyword, followed by its name, parameters, and an indented block.
def calculate_tax(price, tax_rate=0.08):
"""Calculates and returns total tax for a purchase price."""
total_tax = price * tax_rate
return total_tax
# Function Call / Invocation
cost = calculate_tax(100.0) # Uses default tax_rate 0.08 -> 8.0
print(f"Tax: ${cost}")
Core Concept 2
Parameters vs. Arguments
Distinguishing between placeholders in definitions and actual values passed during execution.
Parameters (Placeholders)
Variables listed inside function definition parentheses: def greet(name, age):
Arguments (Values)
Actual data values supplied when calling: greet("Sara", 14) or greet(age=14, name="Sara")
Core Concept 3
`return` vs. `print()` — The Golden Rule
A common beginner mistake is confusing printing text to screen with returning data to code.
`print()` Output
Displays text on the terminal screen for humans to read, but returns None to the caller program!
`return` Value
Hands calculated data back to the calling line so it can be saved in variables or passed to other functions.
Data Flow Diagram
Function Input / Output Pipeline
STEP 1
Arguments PassedValues enter through parameters.
STEP 2
Local ExecutionCalculations happen inside function frame.
STEP 3
Return StatementValue emitted; local memory frame destroyed.
STEP 4
Caller AssignsMain code receives output value.
Core Concept 4
Variable Scope: Local Scope
Variables created inside a function exist ONLY while that function is executing.
def create_player():
player_id = 8891 # Local variable
print(f"Created: {player_id}")
create_player()
print(player_id) # NameError: name 'player_id' is not defined!
Core Concept 5
Variable Scope: Global Scope
Variables defined at the top level of a script are accessible anywhere, but mutating them requires care.
SERVER_IP = "192.168.1.1" # Global constant
def connect():
print(f"Connecting to {SERVER_IP}...") # Read-only access works!
connect()
The LEGB Rule
Python's Scope Resolution Lookup
When Python looks up a variable name, it checks four scope levels in exact order:
L - LOCAL
Inside current function.
E - ENCLOSING
Outer nested functions.
G - GLOBAL
Top level of script.
B - BUILT-IN
Python built-ins (len, sum).
Scope Mutation
The `global` Keyword Warning
Mutating global variables inside functions creates hidden side-effects that lead to unpredictable bugs.
counter = 0
def bad_increment():
global counter
counter += 1 # Modifies global state directly
# Better Pattern: Pass input, return output!
def good_increment(c):
return c + 1
Functional Best Practices
Pure Functions & Side Effects
Pure Function
Given the same inputs, it always returns the exact same output without altering external variables or files.
Side Effect
Modifying a global variable, altering a database, or printing to console inside a math calculation function.
Scenario Analysis
Why Global State Causes Catastrophic Bugs
ARCHITECTURE CHALLENGE
Imagine a multiplayer game engine where 100 player functions all modify a single global health variable simultaneously. What happens when Player 1 takes damage?
Discussion: How does wrapping health inside isolated player scope prevent state corruption?
Spot the Mistake
UnboundLocalError Pitfall
balance = 500
def withdraw(amount):
if balance >= amount: # UnboundLocalError!
balance = balance - amount
return balance
withdraw(50)
Why did this crash? Assigning balance = ... inside the function marks balance as local throughout the function!
Guided Practice
Refactoring Spaghetti Code into Functions
Notice how breaking logic into small functions simplifies reading and testing:
def is_even(num):
return num % 2 == 0
def square(num):
return num * num
# Composition
val = 4
if is_even(val):
print(f"Square of {val} is {square(val)}")
Hands-on Challenge
Password Validator Function
Write a function validate_password(pwd) that returns True if:
- Length is 8 or more characters
- Contains at least one digit
- Does NOT contain spaces
Check Your Understanding
What value is assigned to `res` in `res = print("Hello")`?
Click to reveal answer
Check Your Understanding
In LEGB scope resolution, what does the letter 'E' stand for?
AExternal
BEnclosing
CExplicit
DEnvironment
Click to reveal answer
Check Your Understanding
What happens to local variables when a function finishes executing?
AThey are converted into global variables automatically
BThey are destroyed and removed from RAM
CThey are saved in a hidden text file on disk
DThey freeze and cannot be reused
Click to reveal answer
Check Your Understanding
What is the advantage of default parameter values in functions?
AThey make functions run twice as fast
BThey make arguments optional when calling the function
CThey force all arguments to become strings
DThey prevent functions from returning None
Click to reveal answer
DRY Principle
Don't Repeat Yourself (DRY)
The DRY principle states that every piece of knowledge or logic must have a single, unambiguous representation within a system. Why is copy-pasting code a red flag?
Building Helper Pipelines
Building a Utility Toolkit
Design a set of 3 pure functions for a math game:
1. `calc_score()`
Computes total points based on speed and accuracy.
2. `format_name()`
Strips whitespace and capitalizes player tags.
3. `is_highscore()`
Compares score against leaderboard cutoff.
Chapter Summary
Functions & Scope Cheat Sheet
- Define reusable logic with
def function_name(param1, param2):.
- Always
return values for calculations rather than relying on print().
- Local scope keeps variables isolated inside functions, avoiding global pollution.
- Follow the LEGB rule when tracing variable lookup errors.
Exit Ticket
Trace the Output
x = 10
def foo(x):
x = x + 5
return x
foo(x)
print(x)
Question: What gets printed on the screen? Why is it 10 and not 15?
Looking Ahead
Next Chapter: Lists & Dictionaries
Now that we can organize code into modular functions, we will explore complex data structures to store and manipulate collections of data!