Python is easy to write and easy to write badly. These questions separate people who understand the language’s model — mutability, the GIL, generators — from those who’ve only scripted with it.
Hiring a Python developer is easy. Telling a real one from a convincing résumé is the hard part — and it’s most of what we do. These are grouped by level, because the same question that stretches a junior is a warm-up for a senior.
Junior Python interview questions
0–2 years
Do they understand Python’s object and mutability model?
Why is a mutable default argument dangerous?
Default arguments are evaluated once when the function is defined, so a mutable default like [] or {} persists and accumulates across calls; the fix is a None sentinel. Shows real understanding of when defaults bind.
Writes def f(x=[]) and can’t explain why results leak between calls.
When would you use a generator instead of a list comprehension?
A list comprehension builds the whole list eagerly in memory; a generator is lazy and streams items one at a time, which matters for large or infinite sequences. They weigh memory against reuse.
Builds huge lists in memory where a generator would obviously be correct.
What’s the difference between is and ==?
== compares values, is compares object identity; you use is for None, and small-int/string interning can make is deceptively “work” for values.
Uses is to compare strings or numbers.
Mid-level Python interview questions
2–5 years
Language mechanics and honest awareness of the GIL.
How do decorators work?
A decorator is a callable that takes a function and returns a wrapped one, used for cross-cutting concerns like caching, logging or auth; functools.wraps preserves the original’s metadata. They can write a simple one on the spot.
Uses decorators but can’t explain that they’re just higher-order functions.
What is the GIL and what does it mean for concurrency?
CPython’s Global Interpreter Lock lets only one thread execute bytecode at a time, so threads help I/O-bound work but not CPU parallelism — for that you use multiprocessing or async, and C extensions can release the GIL. Honest about the tradeoffs.
Believes threading gives CPU-bound parallelism in CPython.
How do you manage dependencies and environments?
Per-project virtual environments (venv/poetry/pip-tools), a pinned lockfile for reproducibility, and separating app deps from dev tooling. Reproducible installs across machines and CI.
Installs packages globally with no pinning.
Senior Python interview questions
5+ years
Performance, async and structuring large systems.
How do you approach performance optimisation in Python?
Profile first (cProfile, py-spy), fix the hot path, reach for vectorised libraries or C extensions where it counts, and pick the right data structures before micro-optimising. Measure, don’t guess.
Rewrites code “for speed” with no profiling, or jumps to another language prematurely.
When is asyncio the right tool, and what are the pitfalls?
For high-concurrency I/O-bound workloads, using async-native libraries; the classic pitfall is a blocking call (requests, time.sleep, heavy CPU) inside the loop, which stalls everything — those belong in an executor or separate process.
Mixes blocking calls into async code and wonders why concurrency disappears.
How do you structure a large Python codebase for maintainability?
Clear module boundaries, type hints checked with mypy, dependency injection, no circular imports, and a real test suite. They care about packaging and interfaces, not just files.
One giant module, no typing, tangled circular imports.
Browse the full series on the interview questions hub, or see how we assess engineers in our interview process.