Skip to main content
Back to Python Coding

Python Coding · Cheat Sheet

Reading Functions and Notebooks

Tip: Use your browser's print function (Ctrl+P / Cmd+P) to save as PDF for offline study.

Cheatsheet: Reading Functions and Notebooks

One page for Topic 3 — def blocks, the one Python landmine worth memorizing, and how to audit a notebook like an auditor.


The function-reading checklist

Read every def block in four parts:

PartWhat it isHow to read it
Namedef clean_data(...)A claim by the author, not a guarantee — the body is the fact
ParametersThe inputsInside the function, df means whatever was passed in, not any particular frame in the notebook
Defaultsmin_revenue=0Invisible decisions — a short call like analyze(sales) silently runs with every default; always read the def line to know what a short call really passes
returnThe official productAnything else it does to the outside world is a side effect

A def cell running teaches Python the recipe; the code executes at each call. The fastest verification: trace one call by hand with five concrete rows — thirty seconds tells you more than any amount of reading the name.

The key question: change or copy?

SignalMeaning
inplace=True, or df['col'] = ... inside the bodyMutates the caller's DataFrame — the original changes even if the return value is ignored
.copy() near the top; builds and returns new framesWorks on a copy — original untouched
Call site df = f(df)Pairs with copy-style functions
Bare f(df) on its own lineOnly meaningful for a mutating function — with a copy-style function it's a silent no-op that looks like a cleaning step

A mismatch between function style and call style is a bug you can spot without running anything. Pure functions (compute and return only) are dramatically easier to audit — a good standing instruction for AI: "prefer functions that return a new DataFrame rather than modifying inputs."

Scope: the global-df trap

A function with no parameters that reads df from the surrounding notebook grabs whatever df is at call time — re-load or re-filter between calls and the same call returns different answers. A DataFrame used but not passed as a parameter is a dependency invisible at the call site. Flag it.


Mutable default arguments

Rule: a default value is evaluated once — at def time — not once per call. Every call that omits the argument shares the same object.

def collect(value, results=[]):
    results.append(value)
    return results

collect(10)   # [10]
collect(20)   # [10, 20]  ← the function has memory
Def lineVerdict
def f(x, results=[])Red flag — shared list accumulates across calls
def f(x, cache={})Red flag — same mechanism
def f(x, min_revenue=0) / region='West'Safe — immutable defaults can't accumulate
def f(x, results=None) + if results is None: results = []The safe idiom — fresh list created inside each call

Notebook symptom: metrics that double on every cell re-run but look perfect after a kernel restart. The def cell doesn't re-run, so the default list still holds last run's rows; a rerun appends again — totals exactly 2x, then 3x. Invisible on a fresh run, which is the cruelest property.

Sibling bug: Python passes objects by reference — a function can silently mutate a passed-in DataFrame or list (df['margin'] = ... welds a column onto the caller's frame). Defensive code copies first (df = df.copy()). If a function's job is to compute, verify it didn't also edit — compare the input's shape before and after the call.


Notebook audit

A notebook's displayed outputs are claims about a past session, not properties of the code you're reading.

Execution counters: the flight recorder

  • In [4] = this cell was the 4th run this kernel session. [ ] = never run; any saved output is archaeological.
  • Cells display top to bottom but executed in click order. Counters that don't increase down the page mean some outputs are stale — a sum with [3] sitting below a filter with [5] ran before the filter and includes what the filter excludes.

Hidden state warning

The kernel remembers variables from cells that were edited or deleted after running — no trace on the page, full effect in memory. Combined with out-of-order execution and the mutable-default rerun bug: the page and the session drift apart silently.

Restart and Run All is the only trustworthy state. Afterward, counters go 1, 2, 3... and every output provably came from the code above it. A notebook that errors under Restart and Run All is a finding, not an inconvenience — it can't reproduce its own claims.

The four-stage audit order

StageQuestionCheck
1. Imports + data loadWhat came in, how many rows?len(df) / df.info() at load — your baseline
2. CleaningWhat was dropped or altered, and how many?Every dropna/filter/dedup accounts for its damage; verify the condition afterward, not the printed narration
3. TransformationMerges and groupbys sound?Row counts before/after each merge; grouped totals reconciled against ungrouped; ratio columns checked for mean-of-ratios
4. Conclusion / outputDoes the prose match the output?Physically find the headline number in the last output cell. Markdown never re-executes — stale conclusions over fresh data are routine

Traps

  • Trusting the function name — remove_outliers with subtly different logic in the body; AI names are especially polished.
  • Missing the defaults — every default is a decision the caller didn't visibly make.
  • A discarded return value — bare clean(df) where clean returns a copy is a no-op dressed as a cleaning step.
  • Hidden mutation — a "summary stats" function that also does dropna(inplace=True) on the way through.
  • =[] or ={} in a def line — the bug, or one rerun away from it; the fix is =None + if ... is None.
  • AI patching the symptom — drop_duplicates() bolted on to mask doubled totals leaves the landmine armed.
  • Validating on a fresh run only — the double-counting bug hides after every kernel restart; the state your analyst actually had on screen matters too.
  • Treating displayed output as current — it's a record of the last run, under whatever state existed then; check counters first.
  • Trusting markdown narration — prose describes intent at writing time; code got edited, markdown never re-ran.
  • Skipping the last-mile check — output says 58.0, conclusion says $41: the cheapest bug to catch in all of analytics, and genuinely common.

Aligned to the official Python and pandas documentation.

Make this cheat sheet yours

Personalize this sheet — focus it however you study, or build one from the exact questions you keep getting wrong.

Sign up free to create a personalized cheat sheet.