Python Coding · Cheat Sheet
Reading Python, Not Writing It
Cheatsheet: Reading Python, Not Writing It
One page for Topic 1. AI writes the code; you own the conclusion. "Runs without error" and "computes what was asked" are different claims — the expensive failures are clean runs answering a slightly different question.
The read-verify-decide loop
| Step | What you do | Key move |
|---|---|---|
| 1. Read | Work out what the code actually computes — not what comments, variable names, or the AI's explanation claim | Names are claims by the author; the code is the fact |
| 2. Verify | Cheap checks that need no code-writing | Row counts in vs out; one hand-checked example (one customer, one day); does the conclusion literally appear in the last output cell? |
| 3. Decide | Only now does the number enter your deck | Verify especially when the output looks reasonable — plausible is the most dangerous kind of wrong |
Reading-order habits: open with df.head() + df.info(), confirm a cleaning step exists between read_csv and any math, then re-check df.info() after cleaning.
Dtype table
df.info() shows three things df.head() cannot: row count, non-null counts, and dtypes.
| Dtype | Means | Red flag |
|---|---|---|
int64, float64 | Real numbers | — |
object | Usually strings | A numeric-looking column (revenue) as object = math is broken or misleading |
datetime64[ns] | Real dates — sortable, month-bucketable | Dates as object sort alphabetically and break month grouping |
bool | True/False | Summing counts the Trues (True = 1) |
Coercion traps
| Expression | Result | Why |
|---|---|---|
100 + 5 | 105 | Numeric addition |
'100' + '5' | '1005' | String concatenation — no error |
pd.Series(['1200','800','450']).sum() | '1200800450' | Ten digits of nonsense, no warning |
'9' > '10' | True | String comparison is alphabetical — a filter on string-typed numbers runs cleanly and keeps the wrong rows |
df['revenue'] > 1000 on strings | TypeError | The data is broken, not the filter |
Usual causes of numbers-as-text: currency formatting ("$1,200"), a stray "N/A", or an export tool that quotes everything. After cleaning: revenue should be float64, dates datetime64[ns].
Containers at reading level: [...] = ordered sequence (e.g. a column list), {...} = labeled pairs (e.g. a rename map). Mostly configuration.
The boolean-mask pattern
Every pandas filter, however complicated, is this:
active = df[df['status'] == 'active']
Read inside-out: the inner comparison produces a True/False column (the mask), one value per row; wrapping it in df[...] keeps the True rows.
Combining conditions: & | ~ with parentheses
| Rule | Correct | Broken | Failure mode |
|---|---|---|---|
Use & / | / ~, never and/or/not | (a) & (b) | a and b | Loud: ValueError: truth value of a Series is ambiguous |
| Parenthesize every comparison | (df['revenue'] > 1000) & (df['region'] == 'West') | df['revenue'] > 1000 & df['region'] == 'West' | Confusing: & binds tighter than >, so Python evaluates 1000 & df['region'] first |
| No chained comparisons | (df['x'] > 0) & (df['x'] < 1) | df[0 < df['x'] < 1] | Same ambiguous-truth-value error |
== compares, = assigns | df[df['status'] == 'active'] | df[df['status'] = 'active'] | Syntax error — unlike SQL, a lone = in a Python filter is always a bug |
.loc[rows, cols]
df.loc[df['revenue'] > 1000, ['customer', 'revenue']]
Read as two selections in one: which rows (mask before the comma), which columns (list after it). For keeping rows, df.loc[mask] matches df[mask]; careful authors prefer .loc because it's also the only reliable way to modify a filtered slice (see the view-vs-copy lesson).
Filter-then-count idioms
Most business metrics are a filter plus a count or sum:
| Idiom | Computes |
|---|---|
len(df[df['status'] == 'active']) | Count of matching rows |
(df['status'] == 'active').sum() | Same count — summing a mask counts Trues |
df.loc[df['region'] == 'West', 'revenue'].sum() | West revenue |
The audit question is always the same: does the condition match the business definition? If status == 'active' means "subscription not cancelled" rather than "used the product recently," the metric and its name have parted ways.
Traps
- Trusting the AI's explanation of its own code — the paragraph is intent, not evidence; when code and prose disagree, the code wins.
- Treating a clean run as validation — "it ran" only means the syntax was legal.
- Judging data quality from
df.head()alone —"$1,200"looks like a number on screen; onlydf.info()shows dtypes and missing counts. - Load code that goes straight from
read_csvto math with no dtype check — one stray"N/A"makes a whole column strings. - Assuming missing values announce themselves — sums and means silently skip them.
- Every literal in an AI filter (
1000,'active', a date) is a decision someone made — check that someone was you. - Case/whitespace mismatches —
== 'west'keeps zero rows when the data says'West'; a suspiciously small filtered row count is the tell. - Skipping verification because the number looks right — the plausible wrong number sails straight into a board deck.
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.