- Understand what functions are and why they're important
- Create basic functions using the def keyword
- Call functions and understand execution flow
- Write meaningful function names and documentation
Defining Functions
Imagine you're making sandwiches for a party. Each sandwich requires the same steps: get bread, add filling, add condiments, close the sandwich. Would you write out these instructions 50 times? Of course not! You'd create a "recipe" – a set of instructions you can follow over and over.
Functions are programming's recipes. They're reusable blocks of code that perform a specific task. Instead of writing the same code repeatedly, you define it once and "call" it whenever you need it. This is one of the most powerful concepts in programming – it makes your code shorter, cleaner, and easier to maintain.
What is a Function?
A function is a named block of code that performs a specific task:
What Functions Do
ORGANIZE: Group related code into logical units
"Everything related to greeting goes in greet()"
REUSE: Write once, use many times
Don't repeat yourself (DRY principle)
TEST: Easier to test small, focused functions
Test greet() independently of other code
READ: Functions make code self-documenting
calculate_tax() is clearer than 50 lines of math
Real-World Analogies
| Real-World | Function Equivalent |
|---|---|
| Recipe | A set of cooking instructions you can follow anytime |
| Speed dial | Press one button to call a stored number |
| Assembly line machine | Input materials, get consistent output |
| Form template | Fill in the blanks to create a document |
Creating Your First Function
The Basic Structure
Function Anatomy
def greet():
Parentheses (for parameters)
Function name (you choose)
def keyword (defines a function)
print("Hello!") ← Function body (indented)
print("Welcome!") ← Can have multiple lines
Your First Function
# DEFINING a function (creating the recipe)
def greet():
print("Hello!")
print("Welcome to Python!")
# At this point, NOTHING has printed yet!
# The function exists but hasn't been called
# CALLING the function (following the recipe)
greet()
Output:
Hello!
Welcome to Python!
Key Insight: Define vs Call
Defining vs Calling a Function
DEFINING (creating):
def greet(): ← This CREATES the function
print("Hello!") ← Code is stored, NOT executed
CALLING (using):
greet() ← This EXECUTES the function
greet() ← Can call multiple times!
greet() ← Each call runs the code again
Think of it like:
• Define = Write down a recipe
• Call = Actually cook the dish
Function Naming Rules
Good function names make your code readable:
Naming Rules
# VALID names
def say_hello(): # snake_case (recommended!)
pass
def calculateTotal(): # camelCase (works but not Pythonic)
pass
def greet2(): # Numbers allowed (not at start)
pass
# INVALID names
# def 2greet(): # Can't start with number
# def say-hello(): # No hyphens allowed
# def say hello(): # No spaces allowed
# def def(): # Can't use reserved words
Naming Best Practices
Function Naming Tips
Use verbs - functions DO things
calculate_tax(), send_email(), validate_input()
Be descriptive - say what it does
get_user_age() not gua()
Use snake_case - Python convention
calculate_total_price() not calculateTotalPrice()
Keep it concise - but not cryptic
is_valid() not check_if_the_value_is_valid()
Avoid single letters (except in short loops)
process_data() not p()
Documenting Functions with Docstrings
A docstring is a special string that documents your function:
def greet():
"""Display a friendly greeting message.
This function prints a welcome message to the console.
It doesn't take any parameters or return any value.
"""
print("Hello!")
print("Welcome to Python!")
Why Docstrings Matter
# Without docstring - What does this do?
def process(d):
r = {}
for k, v in d.items():
if v > 0:
r[k] = v
return r
# With docstring - Much clearer!
def filter_positive_values(data):
"""Filter a dictionary to keep only positive values.
Args:
data: A dictionary with numeric values
Returns:
A new dictionary containing only positive values
"""
result = {}
for key, value in data.items():
if value > 0:
result[key] = value
return result
Accessing Docstrings
def greet():
"""Display a greeting message."""
print("Hello!")
# Access the docstring
print(greet.__doc__) # "Display a greeting message."
# Or use help()
help(greet)
Execution Flow
Understanding how Python executes functions:
Execution Flow
Line 1: def greet(): ← Python notes: "greet exists"
Line 2: print("Hello!") ← Stored, not executed
Line 3: print("Bye!") ← Stored, not executed
Line 5: print("Starting...") ← EXECUTES: "Starting..."
Line 6: greet() ← JUMPS to greet function
↓
print("Hello!") ← EXECUTES: "Hello!"
print("Bye!") ← EXECUTES: "Bye!"
↓
Returns to Line 7
Line 7: print("Ending...") ← EXECUTES: "Ending..."
OUTPUT:
Starting...
Hello!
Bye!
Ending...
Code Example
def greet():
print("Hello!")
print("Bye!")
print("Starting...")
greet() # Jump to function, then return
print("Ending...")
Practical Examples
Example 1: Organizing Repeated Code
# WITHOUT functions - repetitive!
print("=" * 30)
print("Welcome to My App")
print("=" * 30)
# ... later in code ...
print("=" * 30)
print("Welcome to My App")
print("=" * 30)
# WITH functions - clean!
def display_header():
"""Display the application header."""
print("=" * 30)
print("Welcome to My App")
print("=" * 30)
display_header() # First use
# ... later ...
display_header() # Reuse easily!
Example 2: Menu System
def show_menu():
"""Display the main menu options."""
print("\n GAME MENU")
print("-" * 20)
print("1. New Game")
print("2. Load Game")
print("3. Settings")
print("4. Exit")
print("-" * 20)
def show_settings():
"""Display settings options."""
print("\n SETTINGS")
print("-" * 20)
print("1. Sound: ON")
print("2. Difficulty: Normal")
print("3. Back to Menu")
print("-" * 20)
# Use the functions
show_menu()
show_settings()
show_menu() # Easy to show menu again!
Example 3: Separating Concerns
def print_receipt_header():
"""Print the top of a receipt."""
print("")
print(" PYTHON STORE ")
print(" Thank you for shopping! ")
print("")
def print_receipt_footer():
"""Print the bottom of a receipt."""
print("" * 30)
print("Visit us again soon!")
print("www.pythonstore.com")
def print_date():
"""Print current date."""
from datetime import datetime
print(f"Date: {datetime.now().strftime('%Y-%m-%d')}")
# Build a receipt
print_receipt_header()
print_date()
print("Items purchased...")
print_receipt_footer()
Common Mistakes
1. Forgetting Parentheses When Calling
def greet():
print("Hello!")
# WRONG - This doesn't call the function!
greet # Just references the function object
# CORRECT
greet() # Actually calls and executes
2. Forgetting the Colon
# WRONG - Missing colon
# def greet()
# print("Hello!")
# CORRECT
def greet():
print("Hello!")
3. Wrong Indentation
# WRONG - Body not indented
# def greet():
# print("Hello!") # IndentationError!
# CORRECT
def greet():
print("Hello!") # Indented with 4 spaces
4. Calling Before Defining
# WRONG - Function doesn't exist yet!
# greet() # NameError: name 'greet' is not defined
# def greet():
# print("Hello!")
# CORRECT - Define first, then call
def greet():
print("Hello!")
greet() # Now it works!
Key Takeaways
Remember These Points
Functions are reusable blocks of code
Define once, call many times
Syntax: def function_name():
(indented body)
Call with: function_name()
Don't forget the parentheses!
Document with docstrings
"""What this function does."""
Use descriptive verb names
calculate_total(), send_email(), is_valid()
Define before you call!
Python reads top to bottom
What's Next?
You've learned how to create and call basic functions! But functions become truly powerful when they can receive input. In the next lesson, we'll explore parameters and arguments – how to pass data into your functions to make them flexible and reusable.
