Python

Verified against Claude Code · 2026-07-27

Get Python code reviewed for idiomaticity, not just correctness

A review prompt that separates "is this correct" from "is this how an experienced Python developer would write it," with a closed set of idiom categories so the review surfaces real foot-guns instead of restating the code.

Claude CodeChatGPT (GPT-5.1)GitHub Copilot ChatCursor 2.1

The prompt

Ready to copy — highlighted parts are example details you can swap.

Review this code for idiomaticity — assume it already works. Your job is to say where it doesn't read like Python an experienced developer would write, and why the idiomatic version is actually better, not just different.

CODE
def get_config(name, cache={}):\n    if cache.get(name) == None:\n        cache[name] = load_from_disk(name)\n    return cache[name]

TARGET PYTHON VERSION
3.12 — flag anything that's idiomatic for an older version but has a cleaner equivalent available now (e.g. pre-3.10 code that could use structural pattern matching, or manual dict-default handling that could use dict.setdefault, defaultdict, or the walrus operator where it genuinely improves clarity rather than just being clever).

STYLE GUIDE
follows Black formatting and Ruff's default rule set; no third-party lint config beyond that

REVIEW CATEGORIES
1. Pythonic idioms — list, dict, or set comprehensions where a manual loop is just building a collection; enumerate or zip instead of manual indexing; context managers for anything with cleanup; pathlib.Path instead of os.path string joining.
2. Truthiness and comparisons — "if not x" versus "if x is None" used correctly, since they are not interchangeable for empty collections versus None; "is" and "is not" for None and singleton checks; never "== None".
3. Mutability bugs — mutable default arguments, accidental aliasing, modifying a list while iterating over it.
4. Error handling style — specific exception types over a bare except with no type, using exceptions for genuinely exceptional cases rather than control flow, not catching and re-raising without adding information.
5. Naming and structure — does a function do one thing; is a "utils" grab-bag hiding what should be several named functions.

OUTPUT FORMAT
For each finding: category, the line or snippet, what's non-idiomatic about it, the idiomatic rewrite, and one sentence on why it's actually better, not just shorter. If a "clever" one-liner would be less readable than the original, say so explicitly and leave it — idiomatic doesn't mean maximally compact.
End with a verdict: how many findings per category, and whether the code is idiomatic enough to ship as-is or needs the listed changes first.
Customize the highlighted detailsoptional — the prompt above already works

Why this works

Separating "is this correct" from "is this idiomatic" as an explicit framing keeps the review from defaulting to the most common failure mode of an open-ended "review this" prompt — restating the code's logic back to the requester instead of judging its style. The closed category list forces coverage of specific, well-documented Python foot-guns that a generic review reliably misses, most notably the mutable default argument bug, where a function like def get_config(name, cache={}) shares one cache dict across every call that doesn't pass one explicitly, because default argument values are evaluated exactly once at function-definition time, not per call. Requiring "why it's actually better, not just shorter" as a mandatory field directly counters a real failure mode of AI-suggested Python rewrites: compressing readable code into a dense one-liner that a human reviewer would reasonably reject in a real pull request for being harder to follow, not more idiomatic. The explicit permission to leave a comparison unchanged when a compact rewrite would hurt readability stops the review from treating brevity as a proxy for good style.

What you get back

Finding 1 [Mutability bugs]: cache={} as a default argument — this dict is created once at function definition and shared across every call that doesn't explicitly pass a cache, so entries silently accumulate across unrelated calls. Rewrite: use cache: dict | None = None, then cache = cache if cache is not None else {} inside the function. This is actually better, not just different, because it removes state that persists between calls without any caller asking for it — a real, reproducible bug source, not a style preference. Finding 2 [Truthiness and comparisons]: cache.get(name) == None — should be cache.get(name) is None, since None is a singleton and == can be overridden by a class's __eq__, making "is" both the correct and the faster check. Verdict: 2 findings (1 mutability, 1 comparison). Needs the mutable-default fix before shipping; the comparison fix is minor but should be bundled in.

Verified against

Claude Code Sonnet 4.6 · 2026-07-27

GitHub Copilot Chat 1.260 (VS Code) · 2026-07-28

Changelog

  • 2026-07-28 Initial publish, verified against Claude Code (Sonnet 4.6) and GitHub Copilot Chat.

Need this built into your business?

If a prompt isn't enough — custom software, built and maintained for you — that's Scult's day job.

EXPLORE CUSTOM SOFTWARE
All Python prompts

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY