40 Module 6 Cheat Sheet
Key concepts, definitions, and code from Chapters 16–18
A quick-reference summary of the essential ideas from Module 6. Click any section heading to jump to the full coverage in the book.
if / elif / else
Conditional statements let Python choose which code to run based on whether a condition is
TrueorFalse.
x = 22.50
if x < 10:
print('low')
elif x < 20:
print('medium-low')
elif x < 30:
print('medium')
else:
print('preferred')- Conditions are checked top to bottom; only the first
Truebranch runs. - Any non-zero number or non-empty object is truthy;
0,0.0,[],"", andNoneare falsy. - Combine conditions with
and/or; Python stops evaluating as soon as the result is known.
Using multiple if statements instead of elif means every condition is checked independently. Use elif when branches are mutually exclusive.
Dictionary Switch Pattern
Python has no
switchstatement. Use a dictionary to map keys to values or functions for clean, fast branching.
# value lookup
prices = {'spam': 1.25, 'ham': 1.99, 'eggs': 0.99}
choice = 'ham'
prices.get(choice, 'Bad choice') # returns 1.99; default if key missing
# function dispatch
actions = {
'upper': str.upper,
'lower': str.lower,
'title': str.title,
}
actions.get('upper', str)('hello') # 'HELLO'Dictionary lookup is faster than a long if/elif chain and easier to update.
Vectorized Conditionals in Pandas
Apply conditional logic across every row of a DataFrame without a Python loop.
| Approach | Best for | Speed |
|---|---|---|
np.where(cond, val_true, val_false) |
Two-outcome conditions | Fastest |
df.apply(func, axis=1) |
Multi-branch or complex logic | Slower |
import numpy as np
# two outcomes — np.where
df['tier'] = np.where(df['sales_value'] > 10, 'high', 'low')
# multi-branch — define a function, then apply
def classify(row):
if row['sales_value'] > 10:
return 'high'
elif row['sales_value'] > 5:
return 'medium'
return 'low'
df['tier'] = df.apply(classify, axis=1)for Loops
A
forloop iterates over every element in a sequence (list, dict, DataFrame, range, …).
# iterate over a range
squared = {}
for n in range(5):
squared[n] = n ** 2 # {0:0, 1:1, 2:4, 3:9, 4:16}
# iterate over a list
for file in file_list:
monthly_data[file] = pd.read_csv(file)
# iterate over dict keys
for key in my_dict:
print(key, my_dict[key])Use enumerate() to get both index and value: for i, val in enumerate(items):
break and continue
| Statement | Effect |
|---|---|
break |
Exit the loop immediately |
continue |
Skip the rest of this iteration; move to the next |
for year in range(2018, 2024):
if year == 2020:
continue # skip 2020, keep going
print(year)
for year in range(2018, 2024):
if year == 2020:
break # stop at 2020
print(year)List & Dict Comprehensions
Comprehensions condense a build-and-append loop into a single readable line.
# list comprehension — all squares
squares = [n ** 2 for n in range(10)]
# with filter — squares of odd numbers only
odd_squares = [n ** 2 for n in range(10) if n % 2 != 0]
# conditional expression — discount or keep original price
prices = [p * 0.8 if p > 100 else p for p in price_list]
# dict comprehension
sq_dict = {n: n ** 2 for n in range(10)}Read a comprehension as: [expression for item in sequence if condition]. The if at the end filters; a ternary … if … else … before for transforms without dropping rows.
while Loops
Use a
whileloop when you don’t know the number of iterations in advance — only a stopping condition.
attempts = 0
found = False
while not found:
result = try_something()
found = result is not None
attempts += 1
print(f'Found after {attempts} attempts')Always ensure the condition can eventually become False, or add a safety counter — otherwise the loop runs forever.
Defining Functions
Wrap repeated logic in a function when you’ve copied the same block more than twice.
def store_sales(data, store, week):
filt = (data['store_id'] == store) & (data['week'] == week)
return data['sales_value'][filt].sum()
store_sales(df, store=309, week=48)Four steps: def + name → parameters → body → return. Without return, the function returns None.
Parameters & Arguments
| Pattern | Syntax | Purpose |
|---|---|---|
| Positional | f(df, 309, 48) |
Order-dependent; error-prone |
| Keyword | f(data=df, store=309, week=48) |
Explicit; order-free |
| Default | def f(x, n=2): |
Optional param with a fallback value |
*args |
def f(*args): |
Variable positional args → tuple |
**kwargs |
def f(**kwargs): |
Variable keyword args → dict |
Default arguments must come after required parameters. def f(n=2, x) raises a SyntaxError.
Type Hints & Docstrings
Type hints signal expected input/output types; docstrings explain intent, parameters, and return values.
def store_sales(data: pd.DataFrame, store: int, week: int) -> float:
"""
Compute total store sales for a given store and week.
Parameters
----------
data : pd.DataFrame
Transactions DataFrame with columns store_id, week, sales_value.
store : int
Store identifier.
week : int
Week of year.
Returns
-------
float
Sum of sales_value for the matching rows.
Examples
--------
>>> store_sales(df, store=309, week=48)
395.6
"""
filt = (data['store_id'] == store) & (data['week'] == week)
return data['sales_value'][filt].sum()Error Handling
Three tools for robust functions:
# raise — signal a specific error
if not isinstance(store, int):
raise TypeError('`store` must be an integer')
# assert — internal sanity check (use for bugs, not user errors)
assert 0 <= discount <= 1, 'Discount must be between 0 and 1'
# try / except — handle expected failures gracefully
try:
result = store_sales(df, store=35, week=48)
except ValueError as e:
print(f'Invalid input: {e}')
result = 0.0
finally:
print('Cleanup runs regardless of error')Use raise / TypeError / ValueError for user-facing validation; assert for internal invariants.
Lambda Functions
A lambda is a short, anonymous function for simple one-off transformations — most useful inside
apply(),map(), orgroupby().
# equivalent definitions
def square(x): return x ** 2
square = lambda x: x ** 2
# common pandas patterns
df['tier'] = df['sales_value'].apply(lambda x: 'high' if x > 10 else 'low')
df.groupby('basket_id').apply(
lambda g: (g['sales_value'] / g['quantity']).mean()
)Lambda bodies are limited to a single expression — no statements, no multi-line logic. For anything more complex, write a named function.
Common Pitfalls
| Mistake | Why it happens | Fix |
|---|---|---|
elif conditions in wrong order |
More general condition checked before specific one; e.g., >= 5000 before >= 10000 |
Put the most restrictive condition first |
| Modifying a list while iterating over it | Loop index goes out of sync as the list shrinks | Iterate over a copy: for item in items[:] |
Forgetting else price in a list comprehension filter |
[price * 0.8 for price in prices if price > 100] silently drops cheap items |
Use ternary form: [price * 0.8 if price > 100 else price for price in prices] |
Infinite while loop |
Condition never becomes False |
Add a counter or break condition as a safety exit |
| Default argument before required parameter | def f(n=2, x) is a SyntaxError |
Required params always come before defaults |
Using df.apply(func) on a large DataFrame for a simple condition |
Row-wise Python loop is much slower than vectorized ops | Use np.where() or pandas boolean indexing for two-outcome conditions |