Filter concepts by levelShowing all levels.

Python · What a 5-Year Engineer Should Explain

What a 5-Year Python Engineer Should Be Able to Explain

A recap, not new mechanics — most of these questions are already covered in depth elsewhere in this topic (and PostgreSQL/System Design/MongoDB); the synthesis questions with no existing home get a concept here

  • Argument passingone binding rule, not two calling conventions
  • Concurrency modelCPU-bound vs I/O-bound, then scale, decides the tool
  • Request lifecycleproxy → WSGI/ASGI server → worker → view
  • Deadlocks & slow queriesa lock-order cycle; a fixed diagnostic checklist

1.How Python passes objects to functions

Python is neither "pass-by-value" nor "pass-by-reference" — calling a function binds the parameter name to the SAME object the argument expression evaluated to, the same way a plain assignment would. What happens next depends only on whether that object is mutable, and whether the function reassigns the parameter or mutates the object in place.

Key features

  • A call binds each parameter name to the argument object itself — identical to name = argument
  • Reassigning a parameter inside the function only rebinds that local name; the caller's name is untouched
  • Mutating the parameter in place (append, [i]=, attribute set) changes the one shared object — visible to the caller
  • Whether a call "looks like" pass-by-value or pass-by-reference depends entirely on the object's mutability, not on how it was passed
  • This is why mutable default arguments leak state: the default object is bound once, at def time, and every call that skips the argument shares it

Command

python
def f(x):
    x = x + [1]     # rebinds the LOCAL name x — caller's list is untouched

def g(x):
    x.append(1)      # mutates the SHARED object — caller sees it too

A call is assignment: parameter = argument. Mutable + mutated in place -> caller sees it. Reassigned -> caller never sees it, mutable or not.

Remember

  • A function call is assignment: parameter = argument — reassigning never reaches the caller, mutating in place always does.
  • Ask CPU-bound-or-I/O-bound first (multiprocessing wins CPU-bound, no exceptions), then concurrency scale (asyncio at real scale, threading otherwise).
  • A request crosses four hops before your view runs: reverse proxy, WSGI/ASGI server, worker, framework routing — skipping the middle two is the most common gap.
  • A deadlock is a genuine wait-for cycle, almost always from opposite-order row locking — the fix is consistent lock ordering, not blind retries.

Pro tip

  • Check query COUNT before reaching for an index — a "slow query" a profiler flags is often N+1 round trips, not one query that itself needs an index.
  • Redis earns its place on ephemeral/cacheable data or its own native structures — not as the sole durable store for data that must never be lost.
  • Most of "what a 5-year engineer should explain" is already covered in depth elsewhere in this project — this section is deliberately thin, pointing at the real concept instead of re-deriving it.
  • Cross-topic answers (deadlocks, slow queries, SQL vs NoSQL, monolith vs microservices) draw on the PostgreSQL, MongoDB, and System Design topics directly via seeAlso.

Next up

  • Review — this closes out the authored Python roadmap sections

Sources

  • ASGI specification — asgi.readthedocs.io
  • PostgreSQL — Explicit Locking (deadlocks) — postgresql.org/docs/current/explicit-locking.html
  • Every example executed on Python 3.14.3 · checked 2026-08-25

Spotted a mistake on this page? Tell us.