def winning_margin(a, b):
"""Return the margin of victory as a percentage of total votes."""
total = a + b
margin = abs(a - b) / total * 100
return round(margin, 1)
print(winning_margin(5200, 4800)) # 4.04.0
Functions, modules, comprehensions, NumPy
def winning_margin(a, b):
"""Return the margin of victory as a percentage of total votes."""
total = a + b
margin = abs(a - b) / total * 100
return round(margin, 1)
print(winning_margin(5200, 4800)) # 4.04.0
abs() ensures the result is positive regardless of which candidate is a and which is b.
def state_classifier(margin):
if margin > 10:
return "Solid"
elif margin >= 5:
return "Likely"
elif margin >= 2:
return "Lean"
else:
return "Toss-up"
for m in [1, 4, 7, 15]:
print(f"{m}: {state_classifier(m)}")1: Toss-up
4: Lean
7: Likely
15: Solid
enumeratesenators = ["bernie sanders", "Elizabeth Warren", "ted CRUZ", "AMY Klobuchar"]
# Part 1 — normalize in place
for idx, name in enumerate(senators):
senators[idx] = name.title()
print(senators)
# Part 2 — print with 1-based numbering
for i, name in enumerate(senators, start=1):
print(f"#{i}: {name}")['Bernie Sanders', 'Elizabeth Warren', 'Ted Cruz', 'Amy Klobuchar']
#1: Bernie Sanders
#2: Elizabeth Warren
#3: Ted Cruz
#4: Amy Klobuchar
The .title() method capitalizes the first letter of each word and lowercases the rest, which handles all four messy inputs uniformly. enumerate(senators, start=1) shifts the counter so the first iteration gives i = 1 instead of 0.
ages = [42, 67, 51, 39, 78, 55, 33, 71]
squares = [a**2 for a in ages]
fifty_plus = [a for a in ages if a >= 50]
labels = ["senior" if a >= 65 else "adult" for a in ages]
print(squares)
print(fifty_plus)
print(labels)[1764, 4489, 2601, 1521, 6084, 3025, 1089, 5041]
[67, 51, 78, 55, 71]
['adult', 'senior', 'adult', 'adult', 'senior', 'adult', 'adult', 'senior']
The conditional-expression form "senior" if a >= 65 else "adult" is different from the filter form if a >= 65 — it returns a value rather than filtering.
states = ["Ohio", "Florida", "Texas", "California", "New York"]
electoral_votes = [17, 30, 40, 54, 28]
ev_dict = {s: v for s, v in zip(states, electoral_votes)}
big_states = {s: v for s, v in ev_dict.items() if v >= 30}
print(ev_dict)
print(big_states){'Ohio': 17, 'Florida': 30, 'Texas': 40, 'California': 54, 'New York': 28}
{'Florida': 30, 'Texas': 40, 'California': 54}
zip pairs the parallel lists. The second comprehension iterates over the first dictionary’s items.
import math
from datetime import date
print(math.log(1000))
print(math.sqrt(2))
print(f"pi ≈ {math.pi:.4f}")
print(f"Today is {date.today()}")6.907755278982137
1.4142135623730951
pi ≈ 3.1416
Today is 2026-06-10
from datetime import date saves you typing datetime.date.today().
import numpy as np
arr = np.arange(1, 11)
print(arr.mean())
print(arr[arr > 5]) # boolean indexing
print(arr * 3) # elementwise multiplication
print(arr.reshape(2, 5))5.5
[ 6 7 8 9 10]
[ 3 6 9 12 15 18 21 24 27 30]
[[ 1 2 3 4 5]
[ 6 7 8 9 10]]
Note that np.arange(1, 11) includes 1 but excludes 11. Boolean indexing (arr[arr > 5]) returns the elements where the condition is True — much faster than a loop on big arrays.
import numpy as np
def summarize_polls(poll_results):
if len(poll_results) == 0:
return None
arr = np.array(poll_results)
return {
"mean": round(float(arr.mean()), 1),
"min": round(float(arr.min()), 1),
"max": round(float(arr.max()), 1),
}
print(summarize_polls([48.5, 51.2, 49.8, 50.3, 47.9]))
print(summarize_polls([])){'mean': 49.5, 'min': 47.9, 'max': 51.2}
None
The float() wrapping converts NumPy scalar types (like np.float64) to plain Python floats, which is cleaner for output. round() then trims to one decimal place.