Control Flow and Functions
From flat lists to real logic
Branches, loops and functions turn data manipulation into logic: iterate over rows, branch on conditions, and package reusable transformations with clear signatures.
What you will learn
- Write readable conditionals and loops over data
- Use enumerate, range and zip idiomatically
- Define functions with clear parameters, defaults and returns
What is this?
Control flow decides what runs: if/elif/else pick branches, for/while repeat work, and break/continue steer loops. Functions package logic with inputs, defaults, and a return value. Together they turn bare dataframes into logic — segmentation rules, cleanup routines, scoring formulas.
Why do you need it?
- Every rule in the business is an if-statement waiting to be encoded.
- Loops apply logic across millions of rows consistently and audibly.
- Functions make rules reusable across reports — fix once, apply everywhere.
- Clear branches are how analysts encode 'if plan is enterprise and usage > X, flag'.
Mental model
A call-center script tree
Control flow and functions
An agent's script branches on answers (if), repeats the greeting script for each caller (for), and hands off to specialist prompts by situation (function call). Analysis logic is the same decision tree, executable at scale.
How it works
- if/elif/else evaluates conditions top-down and runs the first true branch.
- for item in seq iterates in order; range(n) yields numbers 0..n-1; enumerate adds an index.
- zip pairs multiple sequences element-wise for parallel iteration.
- while loops run until a condition breaks; break exits early, continue skips one iteration.
- def f(a, b=1): bodies define functions; defaults copy per-call but mutable defaults persist (a footgun).
- Variables in a function are local unless declared global/nonlocal — scope rules prevent accidental clobbering.
Anatomy of a decision + repetition unit.
Examples
Encoding a segment rule
def segment(plan, usage): if plan == "enterprise": return "key" if usage >= 90: return "upsell" if usage < 10: return "at-risk" return "standard" customers = [("basic", 5), ("enterprise", 40), ("pro", 95)]for i, (plan, usage) in enumerate(customers, start=1): print(i, segment(plan, usage))A readable rule function plus a loop with enumerate turns raw plans and usage into named segments, in order.
In production
- Support analytics flags tickets older than SLA per priority with a branch function.
- A risk review iterates flagged accounts and assigns owners by segment with a loop + lookup.
- An ETL step reuses one transform function across the daily and weekly batches — same logic, both outputs consistent.
Best practices
- One function, one job; name it as a verb (compute_sla, flag_risk).
- Handle the edge default last, and return early for the clearest cases.
- Prefer comprehensions over index-based loops when you only need a transformed list.
- Default to immutable defaults (None) and assign inside the body.
Common mistakes
- Mutating a default list argument and seeing ghost data across calls.
- Forgetting continue/break semantics and over-processing after a match.
- Using a bare while that spins forever because the condition never changes.
- Index math off-by-one with range(len(x)) — enumerate removes that class of bug.
Debugging tips
- Add a print in the branch you think never fires to confirm the logic path.
- When a loop misbehaves, print the first three iterations and the last — usually the ends, not the middle.
- Scope errors ('UnboundLocalError') mean the variable is local; check shadowing.
- For pandas-heavy rule bugs, test the function on three hand-built rows before the real frame.
Interview checkpoint
Hands-on lab
- Write branch logic that classifies customers
- Iterate rows and aggregate with functions
- Refactor repeated logic into one reusable function
Build a Segment Rule Engine
30 min · beginner
Quick quiz
Which prints 0, 1, 2?
A function returns unexpected counts each call because its default list kept growing.