10.19 Hands-on Exercises
Practice programs reinforcing Python list concepts -- an inventory manager class, a todo app, a log analyzer, a CSV processor, and mini projects grouping Amazon EC2 instances and tracking missing Docker containers.
Inventory Manager
A small class wrapping a list to manage a collection of items with add/remove/list operations.
class InventoryManager:
def __init__(self):
self.items = []
def add(self, item):
self.items.append(item)
def remove(self, item):
if item in self.items:
self.items.remove(item)
def list_all(self):
return self.items
>>> inv = InventoryManager()
>>> inv.add("server01"); inv.add("server02")
>>> inv.remove("server01")
>>> inv.list_all()
['server02']
Todo App
A list of dicts, each representing one task — a common lightweight data model before reaching for a database.
todos = []
def add_todo(task):
todos.append({"task": task, "done": False})
def complete_todo(index):
todos[index]["done"] = True
>>> add_todo("Deploy app"); add_todo("Review PR")
>>> complete_todo(0)
>>> todos
[{'task': 'Deploy app', 'done': True}, {'task': 'Review PR', 'done': False}]
Log Analyzer
Counting occurrences of different severity levels across a list of log lines.
def analyze_logs(lines):
return {
"errors": sum(1 for l in lines if "ERROR" in l),
"warnings": sum(1 for l in lines if "WARNING" in l),
}
>>> analyze_logs(["INFO x", "ERROR y", "WARNING z", "ERROR w"])
{'errors': 2, 'warnings': 1}
CSV Processor
Parsing a CSV blob into a list of dicts, ready for further filtering or aggregation.
import csv, io
def process_csv(text):
return list(csv.DictReader(io.StringIO(text)))
>>> process_csv("name,age\nAlice,30\nBob,25")
[{'name': 'Alice', 'age': '30'}, {'name': 'Bob', 'age': '25'}]
Mini Projects
Server inventory tool — group a list of Amazon EC2-style instance records by their current state, the core logic behind any fleet-status dashboard:
def group_by_state(instances):
result = {}
for inst in instances:
result.setdefault(inst["state"], []).append(inst["id"])
return result
>>> group_by_state([
... {"id": "i-1", "state": "running"},
... {"id": "i-2", "state": "stopped"},
... {"id": "i-3", "state": "running"},
... ])
{'running': ['i-1', 'i-3'], 'stopped': ['i-2']}
Docker tracker — combine the container-membership check from 10.15 Lists in DevOps with a list comprehension to report which expected containers are missing from the running list:
expected = ["nginx", "redis", "postgres", "celery"]
running = ["nginx", "redis", "postgres"]
>>> missing = [c for c in expected if c not in running]
>>> missing
['celery']
Backup manager — keep only the N most recent backups, discarding the rest, a common retention-policy script:
def rotate_backups(backups, keep=3):
return sorted(backups, reverse=True)[:keep]
>>> rotate_backups([
... "backup_2026-01-01", "backup_2026-01-05",
... "backup_2026-01-10", "backup_2026-01-15",
... ], keep=2)
['backup_2026-01-15', 'backup_2026-01-10']
- AWS inventory report — combine the Amazon EC2 filtering pattern from 10.15 Lists in DevOps with the grouping function above to build a full multi-region, multi-state resource report.
- Kubernetes inventory — combine the pod-filtering pattern from 10.15 Lists in DevOps with count-by-prefix logic to report how many pods each deployment currently has running.
Quick Interview Answer
“These exercises combine the chapter’s tools into small, realistic programs: the inventory manager and todo app wrap a list inside a class or module-level state with add/remove/query operations; the log analyzer and CSV processor lean on comprehensions and the
csvmodule rather than manual parsing; and the mini projects — grouping Amazon EC2 instances by state, diffing expected vs. running Docker containers, rotating backups by keeping the N most recent — are all variations on the same filtering-and-grouping comprehension pattern applied to real infrastructure data.”
Common Mistakes
- Mutating
self.itemsfrom outside theInventoryManagerclass directly instead of going throughadd()/remove(), bypassing whatever validation those methods might do. - Using a list index directly as a todo item’s permanent identifier (
complete_todo(index)) — removing an earlier item shifts every later index, silently completing the wrong task. - Sorting backup filenames as plain strings and assuming that sorts chronologically — it only works if the naming format is zero-padded and lexicographically ordered the same as chronological order, as in the ISO-style dates used above.
Add More Questions to This Guide
Know a question that should be here? Share it and help the community!
Open Google Form