Crash Courses · Masters
Functions, Scope & Reusable Code
Write clean, reusable functions using parameters, return values, *args, **kwargs, and docstrings.
14 min read+170 XP on completionCert: Python Crash Course
Tap any word in the text below to start reading from there.
Functions, Scope & Reusable Code
Defining and Calling Functions
def greet(name):
"""Return a greeting string for the given name."""
return f"Hello, {name}!"
message = greet("Jordan")
print(message) # Hello, Jordan!
# A function without return implicitly returns None
def log(msg):
print(f"[LOG] {msg}")
result = log("started")
print(result) # None---
Default Parameters
def create_user(name, role="viewer", active=True):
return {"name": name, "role": role, "active": active}
# Use defaults
print(create_user("Jordan"))
# {'name': 'Jordan', 'role': 'viewer', 'active': True}
# Override specific defaults
print(create_user("Owen", role="admin"))
# {'name': 'Owen', 'role': 'admin', 'active': True}
# ⚠️ COMMON BUG: mutable defaults persist across calls
def append_item(item, lst=[]): # DON'T DO THIS
lst.append(item)
return lst
print(append_item(1)) # [1]
print(append_item(2)) # [1, 2] — same list reused!
# CORRECT: use None as default, create list inside function
def append_item(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst---
*args: Variable Positional Arguments
def sum_all(*args):
"""Sum any number of numeric arguments."""
return sum(args) # args is a tuple inside the function
print(sum_all(1, 2, 3)) # 6
print(sum_all(10, 20, 30, 40)) # 100
print(sum_all()) # 0
def log_events(level, *messages):
for msg in messages:
print(f"[{level.upper()}] {msg}")
log_events("info", "Server started", "Listening on port 8000", "Ready")
# [INFO] Server started
# [INFO] Listening on port 8000
# [INFO] Ready---
kwargs: Variable Keyword Arguments
def build_query(**filters):
"""Build a SQL-style query from keyword filters."""
conditions = [f"{k} = {repr(v)}" for k, v in filters.items()]
return "WHERE " + " AND ".join(conditions) if conditions else ""
print(build_query(status="active", role="admin"))
# WHERE status = 'active' AND role = 'admin'
# Combine all parameter types: positional, *args, keyword, **kwargs
def fn(required, *args, keyword="default", **kwargs):
print(f"required={required}")
print(f"args={args}")
print(f"keyword={keyword}")
print(f"kwargs={kwargs}")
fn("hello", 1, 2, 3, keyword="custom", x=10, y=20)
# required=hello
# args=(1, 2, 3)
# keyword=custom
# kwargs={'x': 10, 'y': 20}---
Scope: LEGB Rule
x = "global" # Global scope
def outer():
x = "enclosing" # Enclosing scope
def inner():
x = "local" # Local scope
print(x) # local — local takes priority
inner()
print(x) # enclosing
outer()
print(x) # global
# global keyword — modify a global inside a function (use sparingly)
count = 0
def increment():
global count
count += 1
increment()
increment()
print(count) # 2
# nonlocal keyword — modify enclosing scope variable
def make_counter():
total = 0
def add(n):
nonlocal total
total += n
return total
return add
counter = make_counter()
print(counter(5)) # 5
print(counter(3)) # 8---
Docstrings
def calculate_stats(numbers):
"""
Calculate descriptive statistics for a list of numbers.
Args:
numbers: A list of numeric values. Must be non-empty.
Returns:
A dict with keys: min, max, mean, total, count.
Raises:
ValueError: If the input list is empty.
Example:
>>> calculate_stats([1, 2, 3, 4, 5])
{'min': 1, 'max': 5, 'mean': 3.0, 'total': 15, 'count': 5}
"""
if not numbers:
raise ValueError("Cannot calculate stats on an empty list")
return {
"min": min(numbers),
"max": max(numbers),
"mean": sum(numbers) / len(numbers),
"total": sum(numbers),
"count": len(numbers),
}
# Access docstring
print(calculate_stats.__doc__)
help(calculate_stats)---
Lambda Functions (One-Line Anonymous Functions)
# lambda args: expression
double = lambda x: x * 2
print(double(5)) # 10
# Most useful as callbacks — sorting, filtering
people = [{"name": "Tony", "age": 34}, {"name": "Aria", "age": 28}]
people.sort(key=lambda p: p["age"])
print(people) # Aria first (28), then Tony (34)
# But for anything beyond one line, use def — it's clearerReading progress
0% read
In this module
def
return
*args
**kwargs
0%