Python developer interviews in 2026 still start with lists, dictionaries, and functions—but the bar has moved toward production judgment: when to use asyncio instead of threads, how Django ORM queries scale, and whether your FastAPI service loads a model once or on every request. Hiring managers report that strong resumes fail when candidates cannot explain the event loop or defend framework trade-offs under follow-up questions.
Below are 45 questions for Python developer, full stack Python developer, and senior backend loops—from core language and OOP through Django, FastAPI, asyncio, testing, and deployment. For OOP fundamentals and SOLID (language-agnostic with Java emphasis), see OOP interview questions. For dedicated Django interview prep for experienced professionals, see Django interview questions for experienced developers. For Apache Kafka and event pipelines, see Kafka interview questions. For Kubernetes interview questions when deploying containers, see Kubernetes interview questions. For PostgreSQL interview questions with psycopg/SQLAlchemy stacks, see PostgreSQL interview questions. Open each answer after you try the question yourself. For pandas interview questions and DataFrame depth, see pandas interview questions. For broader ML and statistics prep, see data science interview questions. For browser-to-database integration across stacks, see full stack developer interview questions.
Interview context and how to prepare
What do Python developer interviews actually test?
Python interviews test whether you can ship and debug real services, not only recite syntax.
| Level | Typical focus |
|---|---|
| Junior (0–2 yrs) | Types, control flow, comprehensions, basic OOP, file I/O, simple functions |
| Mid (3–5 yrs) | Decorators, generators, error handling, SQL/ORM, pytest, REST API basics |
| Senior (6+ yrs) | GIL and concurrency choice, ORM performance, async services, CI/CD, system design, trade-offs |
| Full stack Python | Above plus frontend integration, auth flows, schema design, deployment |
Live coding often includes:
- List/dict/string manipulation
- Parsing JSON or CSV
- Writing a small API handler or data transform
- Debugging mutable-default or async bugs
A strong answer connects language features to production scenarios (retries, large files, query counts), not definitions alone.
Python developer vs full stack Python developer — what changes in interviews?
A Python developer loop usually emphasizes backend depth: language internals, frameworks, databases, testing, and deployment.
A full stack Python developer loop adds UI integration:
| Area | Python backend focus | Full stack Python add-on |
|---|---|---|
| APIs | Django REST / FastAPI routes, validation, auth | CORS, cookie vs JWT from React/Vue |
| Data | ORM, migrations, SQL | Pagination and loading states in UI |
| Architecture | Service layers, workers (Celery) | End-to-end feature ownership |
| Interview task | CRUD endpoint, query optimization | Form + API + DB in one session |
Common full stack stacks in 2026:
- Django + React — batteries-included backend, admin, ORM conventions
- FastAPI + React/Vue — async APIs, OpenAPI contracts, microservices
- Flask + SPA — minimal core; you justify extensions (Flask-Login, SQLAlchemy)
What is a typical Python developer interview loop?
Most companies run 4–6 rounds:
| Round | Duration | Focus |
|---|---|---|
| Recruiter / HM screen | 30 min | Background, stack, projects |
| Core Python | 45–60 min | Types, OOP, decorators, data structures |
| Framework deep dive | 45–60 min | Django ORM, FastAPI async, or Flask patterns |
| Live coding | 45–90 min | Algorithms, parsing, API snippet, debugging |
| System design | 45–60 min | Services, queues, caching—senior roles |
| Behavioral | 30–45 min | Ownership, incidents, mentoring |
Take-home assignments may ask for a small REST API with tests and a README—quality of error handling and tests often matters more than feature count.
A strong candidate thinks aloud during live coding and states assumptions before coding.
What is a realistic 4–6 week prep plan?
| Week | Focus | Output |
|---|---|---|
| 1 | Core Python refresh — mutability, comprehensions, functions, args/kwargs | Fix 10 small functions without docs |
| 2 | OOP, decorators, generators — yield, context managers | Implement retry decorator + generator pipeline |
| 3 | Framework track (pick JD match) — Django ORM or FastAPI async | One CRUD API with validation and tests |
| 4 | SQL, pytest, mocking | Optimize one N+1 scenario; write parametrized tests |
| 5 | Concurrency — threading vs multiprocessing vs asyncio | Explain GIL trade-offs with one I/O-bound example |
| 6 | System design + behavioral STAR stories | Sketch notification or ingestion service; rehearse 3 stories |
Ship one mini-project (todo API, URL shortener, or ingestion script) with Docker and pytest—not only flashcards.
Python fundamentals and the object model
Explain mutable vs immutable types in Python.
Immutable objects cannot change after creation: int, float, str, tuple (if all elements immutable), frozenset, bytes.
Mutable objects can change in place: list, dict, set, most user-defined classes.
Why interviewers care:
| Scenario | Pitfall |
|---|---|
| Dict key | Keys must be hashable → no mutable lists as keys |
| Default function args | Shared mutable default (see Q6) |
| Thread safety | Mutating shared lists/dicts without locks |
| Copy semantics | Shallow copy shares nested mutable objects |
s = "hello"
# s[0] = "H" # TypeError — str is immutable
items = [1, 2]
items.append(3) # mutates list in placeFor a deeper comparison of built-in collections, see list vs set vs tuple vs dictionary.
A strong answer ties mutability to bugs you've seen (shared state, unexpected aliasing), not only definitions.
What is the mutable default argument trap?
Default arguments are evaluated once at function definition time—not on each call.
def append_item(item, bucket=None):
if bucket is None:
bucket = []
bucket.append(item)
return bucket
print(append_item(1)) # [1]
print(append_item(2)) # [2] — safe patternBroken pattern (common interview trap):
def bad_append(item, bucket=[]):
bucket.append(item)
return bucket
print(bad_append(1)) # [1]
print(bad_append(2)) # [1, 2] — same list reused!Fix: use None as sentinel and create a fresh list inside the function.
Interviewers want you to explain object identity (id(bucket) stays same across calls in the bug version).
When do you use list, tuple, set, or dict?
| Type | Ordered | Mutable | Duplicates | Typical use |
|---|---|---|---|---|
list |
Yes | Yes | Yes | Sequences, stacks, ordered work |
tuple |
Yes | No | Yes | Fixed records, dict keys, return bundles |
set |
No | Yes | No | Membership, dedupe, unique tags |
dict |
Yes* | Yes | Keys unique | Lookup, counting, JSON-like maps |
*Insertion order preserved since Python 3.7+ (language guarantee 3.8+).
Choose tuple for hashable records; set for O(1) average membership; dict for key→value maps; list when you need order with mutation.
A strong answer mentions time complexity (in on list is O(n), on set/dict is O(1) average).
List comprehension vs generator expression — when does each win?
List comprehension — builds full list in memory:
squares = [n * n for n in range(1_000_000)]Generator expression — lazy, constant memory:
squares = (n * n for n in range(1_000_000))| Case | Prefer |
|---|---|
| Small data, need indexing/reuse | List comprehension |
| Large files/streams, pipeline | Generator |
| Sum/max/any once | sum(n*n for n in range(...)) |
Interviewers link this to 50GB log processing—you cannot materialize all lines as a list.
See python yield for generator functions with state.
Does Python pass by value or by reference?
Python is pass-by-object-reference (sometimes called "pass by assignment"):
- Names bind to objects
- Rebinding a parameter (
x = x + 1on int) does not affect caller - Mutating a shared object (
lst.append(1)) does affect caller
def grow(lst):
lst.append(99)
data = [1]
grow(data)
print(data) # [1, 99]A strong answer avoids saying only "references"—explain rebind vs mutate with a quick example.
What is the difference between is and ==?
==compares values (calls__eq__)iscompares object identity (id(a) == id(b))
Use is only for singletons like None, True, False:
x = None
x is None # idiomatic
"a" * 1000 == "a" * 1000 # True
"a" * 1000 is "a" * 1000 # may be False — separate objectsInterview trap: never use is for small integer caching folklore without context—focus on None checks.
Shallow copy vs deep copy?
import copy
original = [[1], [2]]
shallow = copy.copy(original)
deep = copy.deepcopy(original)
original[0].append(99)
print(shallow[0]) # [1, 99] — nested list shared
print(deep[0]) # [1] — fully independent| Method | Copies | Nested mutable objects |
|---|---|---|
copy.copy |
Top level | Shared |
copy.deepcopy |
Recursive | Independent |
Use deep copy when handing off nested structures you must not alias (config snapshots, test fixtures).
Functions, decorators, and closures
Explain *args and **kwargs.
*args— tuple of extra positional arguments**kwargs— dict of extra keyword arguments
def demo(a, *args, b=10, **kwargs):
return a, args, b, kwargs
demo(1, 2, 3, b=20, c=30)
# (1, (2, 3), 20, {'c': 30})Common uses:
- Wrapper functions that forward to inner APIs
- Decorators that accept arbitrary signatures
- Framework hooks (Django views, pytest fixtures)
Full examples: python kwargs and args.
What is a decorator and when would you write one?
A decorator wraps a function to add cross-cutting behavior without duplicating code:
- Logging, timing, auth checks
- Retry with backoff on flaky HTTP calls
- Caching (
functools.lru_cache)
Mechanically: @decorator applies func = decorator(func).
A strong answer names one production use (retry on payment API, auth on admin routes) and mentions functools.wraps to preserve __name__ and docstrings for debugging.
How would you write a retry decorator with exponential backoff?
Interviewers test closures, exceptions, and real API resilience:
import functools
import time
def retry(times=3, base_delay=0.1):
def decorator(fn):
@functools.wraps(fn)
def wrapper(*args, **kwargs):
last_exc = None
for attempt in range(times):
try:
return fn(*args, **kwargs)
except Exception as exc:
last_exc = exc
time.sleep(base_delay * (2 ** attempt))
raise last_exc
return wrapper
return decoratorSenior follow-ups:
- Add jitter to avoid thundering herd
- Retry only specific exceptions (
requests.Timeout) - Log attempt count and final failure
I ran this pattern on Python 3.13—the third attempt succeeds after two deliberate failures.
Lambda vs def — when to use each?
lambda |
def |
|
|---|---|---|
| Name | Anonymous | Named, reusable |
| Body | Single expression | Statements, docstring |
| Use | Short key=/map callbacks |
Everything else |
sorted(users, key=lambda u: u["last_login"])Prefer def for anything non-trivial—lambdas are hard to debug and cannot contain assignments.
See python lambda function for more examples.
What is a closure?
A closure is a function that remembers variables from its enclosing scope after the outer function returns.
Decorators rely on closures to hold configuration (times=3 in the retry decorator).
Interviewers may ask you to fix a classic loop bug:
# Bug: all lambdas see final i
funcs = [lambda: i for i in range(3)]
# Fix: default arg binds i at definition time
funcs = [lambda i=i: i for i in range(3)]A strong answer explains late binding in comprehension lambdas.
Object-oriented Python
Difference between @staticmethod, @classmethod, and instance methods?
| Kind | First arg | Typical use |
|---|---|---|
| Instance method | self |
Uses instance state |
@classmethod |
cls |
Alternative constructors, factory methods |
@staticmethod |
None | Utility grouped with class namespace |
class User:
def __init__(self, name):
self.name = name
@classmethod
def from_dict(cls, data):
return cls(data["name"])
@staticmethod
def validate_name(name):
return bool(name and name.strip())Use classmethod when you need polymorphic construction; staticmethod when logic belongs near the class but needs no self or cls.
How does inheritance and MRO work in Python?
Python supports multiple inheritance. Method Resolution Order (MRO) is the linearization C3 algorithm uses to pick which parent method runs.
class A:
def ping(self):
return "A"
class B(A):
def ping(self):
return "B"
class C(A):
def ping(self):
return "C"
class D(B, C):
pass
print(D().ping()) # B
print(D.mro()) # D, B, C, A, objectInterviewers want super() used correctly in cooperative multiple inheritance—not only single-parent examples.
A strong answer mentions mixins (small reusable behaviors) vs deep hierarchies.
What are dataclasses and when do you prefer them?
@dataclass generates __init__, __repr__, and comparison methods from typed fields—less boilerplate than manual classes.
from dataclasses import dataclass
@dataclass(frozen=True)
class Point:
x: int
y: int| Prefer dataclass | Prefer plain class / Pydantic |
|---|---|
| Internal DTOs, config records | Rich validation at API boundary |
frozen=True for hashable value objects |
FastAPI request models (Pydantic v2) |
Senior note: dataclasses are not a replacement for domain logic—keep behavior methods purposeful.
Abstract base classes vs duck typing?
Duck typing: "If it quacks like a duck, use it"—no inheritance required; rely on protocols (file.read(), iterable behavior).
ABC (abc module): enforce interface contracts for frameworks and plugins.
from abc import ABC, abstractmethod
class Repository(ABC):
@abstractmethod
def get(self, id: int): ...Use ABCs when teams need explicit contracts; use duck typing for flexible utilities and tests (fakes without subclassing).
When would you use __slots__?
__slots__ restricts instance attributes to a fixed set—saves memory and can speed attribute access by avoiding per-instance __dict__.
Trade-offs:
| Benefit | Cost |
|---|---|
| Lower memory for millions of objects | Cannot add arbitrary attributes |
| Faster attribute lookup | Multiple inheritance gets tricky |
Use for high-volume value objects (event streams, parsers)—not default for every model (Django ORM models use their own machinery).
Generators, iterators, and memory
What is a generator and why use one over a list?
A generator produces items lazily via yield (or a generator expression). A list materializes all items at once.
def read_lines(path):
with open(path, encoding="utf-8") as f:
for line in f:
yield line.strip()Benefits:
- Constant memory on large files
- Pipeline-friendly (parse → filter → aggregate)
- Can represent infinite sequences
Interview answer for "process 50GB CSV": generator or chunked pandas.read_csv(chunksize=...), never readlines() into RAM.
Iterable vs iterator?
- Iterable — has
__iter__()returning an iterator (list,dict, generator function result) - Iterator — has
__iter__()and__next__(), raisesStopIterationwhen exhausted
it = iter([1, 2, 3])
next(it) # 1Generators are iterators. You can only consume a one-shot iterator once unless you recreate it.
What does yield from do?
yield from delegates to another iterable/generator—flattens nested iteration and forwards send()/throw() in advanced coroutine code.
def chain(*iterables):
for it in iterables:
yield from it
list(chain([1, 2], [3])) # [1, 2, 3]Practical use: composing pipelines without nested loops; async has async for analog patterns.
GIL, threading, multiprocessing, and asyncio
What is the GIL and why does it matter?
The Global Interpreter Lock (GIL) in CPython allows only one thread to execute Python bytecode at a time in a single process.
Implications:
| Workload | Typical approach |
|---|---|
| CPU-bound (math, encoding) | multiprocessing, C extensions, or offload to Rust/Go worker |
| I/O-bound (HTTP, DB, disk) | threading or asyncio while waiting on I/O |
| Mixed | Process pool for CPU + async for I/O |
A strong answer does not say "Python can't do concurrency"—it qualifies parallel CPU vs concurrent I/O.
Threading vs multiprocessing vs asyncio — how do you choose?
| Model | Parallel CPU? | Best for | Caveat |
|---|---|---|---|
| threading | No (GIL) | Blocking I/O libraries | Watch shared mutable state |
| multiprocessing | Yes (separate processes) | CPU-heavy transforms | Higher memory, serialization cost |
| asyncio | No | Many concurrent I/O connections | Requires async-compatible libraries |
Example asyncio skeleton:
import asyncio
async def fetch(url):
await asyncio.sleep(0.01) # stand-in for I/O
return url
async def main():
results = await asyncio.gather(*(fetch(u) for u in ["a", "b", "c"]))
print(results)
asyncio.run(main())Senior follow-up: uvicorn + FastAPI runs ASGI event loop; blocking ORM calls need thread pool (run_in_executor) or async drivers.
When would you build a Python service with asyncio?
Choose asyncio when:
- High fan-out I/O (many HTTP/DB/WebSocket clients)
- Latency-sensitive API aggregating multiple backends
- Stack is async-native (FastAPI,
httpx, asyncpg)
Avoid assuming asyncio fixes CPU bottlenecks—profile first.
Architecture sketch for notification fan-out:
- FastAPI accepts request
asyncio.gathercalls downstream services- Push to queue (Redis/RabbitMQ) for slow work
- Worker process (Celery/sync) for CPU-heavy tasks
Compare with Node.js event loop interviews—similar I/O concurrency story, different runtime.
Common asyncio mistakes in interviews?
| Mistake | Fix |
|---|---|
Calling time.sleep() in async route |
await asyncio.sleep() or run blocking code in executor |
| Blocking DB driver in async handler | Async driver or asyncio.to_thread() |
| Fire-and-forget tasks without tracking | Store Task refs; handle exceptions |
| Shared mutable global state | Pass dependencies; use connection pools |
| "Async everywhere" for CPU work | Process pool or sync workers |
Interviewers reject candidates who say asyncio gives multi-core parallelism for Python CPU work without mentioning processes.
How do you avoid blocking the event loop?
- Use async libraries (
httpx.AsyncClient,asyncpg) - Wrap unavoidable sync calls:
await asyncio.to_thread(blocking_fn, arg) - Offload heavy CPU to Celery/RQ workers or multiprocessing pool
- Set timeouts on external calls
- Monitor event loop lag in production (metrics, slow request logs)
Django note: traditional sync views under WSGI are fine for many apps; ASGI + async views require the same discipline.
Error handling, context managers, and testing
Explain try / except / else / finally.
try:
result = risky()
except ValueError as exc:
handle(exc)
else:
# runs only if no exception
log_success(result)
finally:
# always runs — cleanup
cleanup()Best practices interviewers expect:
- Catch specific exceptions, not bare
except: - Re-raise with
raiseorraise NewError(...) from exc - Use
elseto keep success path readable
More patterns: python try except.
What is a context manager and why use with?
Context managers guarantee setup/teardown (files, locks, DB transactions) via __enter__/__exit__ or @contextmanager.
from contextlib import contextmanager
@contextmanager
def tag(name):
print(f"[{name}] start")
try:
yield name
finally:
print(f"[{name}] end")
with tag("job") as label:
process(label)Prefer with open(...) over manual close() in finally—fewer leaked handles under exceptions.
What pytest features do interviewers expect?
| Feature | Use |
|---|---|
assert |
Simple tests without boilerplate |
| fixtures | Shared DB, client, sample data |
@pytest.mark.parametrize |
Table-driven edge cases |
monkeypatch / unittest.mock |
Isolate external APIs |
tmp_path |
File system tests |
Example parametrized test:
import pytest
@pytest.mark.parametrize("text,expected", [
("", False),
("a", True),
])
def test_validate_name(text, expected):
assert User.validate_name(text) == expectedSenior bar: tests that catch regressions (N+1 query count, auth failures), not only happy path.
How do you mock external APIs in Python tests?
- Patch at use site (
@patch("myapp.client.requests.get")) - Return
Responsefakes with controlled status/body - Assert call count and payloads for contract tests
- For async, use
pytest-asyncioand mockAsyncClient
Avoid hitting real payment or email APIs in unit tests—use interfaces + fakes so CI stays fast and deterministic.
Django, FastAPI, and Flask
Walk through the Django request lifecycle.
High-level path (WSGI/ASGI):
- Server receives HTTP request
- Django middleware chain (security, sessions, auth, CSRF)
- URL resolver → view
- View uses ORM/forms/serializers
- Middleware processes response
- Connection cleanup / logging
Senior candidates mention CSRF on cookie-session apps, authentication middleware, and database connection handling—not only "URL → view → template."
Follow-up: WSGI sync vs ASGI async entry; choose ASGI when you need async views or WebSockets.
What is the N+1 query problem and how do you fix it in Django?
N+1: one query for parent rows + one per row for related data.
# Bad: hits DB per book.author
for book in Book.objects.all():
print(book.author.name)
# Better: select_related for ForeignKey
for book in Book.objects.select_related("author"):
print(book.author.name)| Tool | Join type |
|---|---|
select_related |
SQL JOIN — FK / OneToOne |
prefetch_related |
Separate query + Python join — reverse FK, M2M |
Senior nuance: prefetch_related on huge related sets can over-fetch—sometimes a targeted Prefetch queryset or raw SQL wins. Profile with django-debug-toolbar or query logging.
Django vs FastAPI — when would you use each?
| Factor | Django | FastAPI |
|---|---|---|
| Admin, auth, ORM batteries | Strong built-ins | Bring your own / SQLAlchemy |
| Team skill | Full-stack monoliths | Microservices, ML APIs |
| Async / OpenAPI | Improving; not the core story | Native async, auto schema |
| Maturity | Huge ecosystem | Lean, fast to ship APIs |
Hybrid pattern: Django for admin/auth + FastAPI for latency-sensitive read APIs—justify operational cost (two deployables, shared auth).
A strong answer picks based on team, traffic shape, and maintenance, not hype.
Why does FastAPI use Pydantic models?
Pydantic provides:
- Runtime validation of request/response bodies
- Clear 422 errors for clients
- Type hints → OpenAPI / Swagger docs
- Pydantic v2 Rust core → faster validation
Senior angle: schema is the contract between frontend and backend—reduces "works on my machine JSON" bugs until integration tests exist.
from pydantic import BaseModel, Field
class CreateUser(BaseModel):
email: str = Field(min_length=3)
age: int = Field(ge=18)How do you handle auth in Flask when the framework is minimal?
Flask does not ship auth—you choose:
| Approach | Fit |
|---|---|
| Flask-Login | Session/cookie web apps |
| JWT middleware | SPA + API token |
| OAuth lib | Social / enterprise SSO |
Senior response: ask clarifying questions (SPA vs server-rendered? refresh tokens?) before picking.
For DB patterns with Flask, see Flask SQLAlchemy.
Full stack Python, SQL, and production
What steps matter when building a production Python REST API?
- Validation at boundary (Pydantic, DRF serializers)
- AuthN/AuthZ — JWT or session; role checks on sensitive routes
- Structured logging + request IDs
- Health/readiness endpoints
- Migrations (Django/Alembic) with safe rollout plan
- Tests — unit + API integration
- Container image (slim base, non-root user)
- CI — lint, test, type check (
ruff,mypyoptional)
Interviewers want operational awareness—not only @app.get.
Packaging reference: create a Python package.
How does a full stack Python developer connect React to Django or FastAPI?
Typical flow:
- React form →
fetch('/api/items', { method: 'POST', body: JSON }) - FastAPI/Django validates body, persists via ORM
- JSON response → React updates state (React Query/SWR)
- CORS configured for dev origin; cookies need
credentials+ CSRF strategy
| Auth style | Browser note |
|---|---|
| JWT in memory/header | CORS + XSS discipline |
| HttpOnly cookie | CSRF protection on mutating routes |
Cross-read full stack developer interview questions for layer-integration scenarios beyond Python-only depth.
How much SQL do Python interviews expect?
Backend Python roles expect you to read and write SQL, not only ORM magic:
- JOINs, GROUP BY, indexes
- Explain an EXPLAIN plan at high level
- Know when ORM generates inefficient SQL
Practice with SQL technical interview questions.
Strong answer: "I use ORM for productivity but drop to SQL for reporting queries and performance fixes."
What deployment and CI/CD topics appear for Python developers?
Common topics:
- Docker multi-stage builds,
uv/piplayer caching - Gunicorn/uvicorn workers vs async workers
- Environment config — 12-factor, secrets not in git
- Migrations on deploy — expand/contract pattern
- Celery/RQ for background jobs
- Observability — Sentry, Prometheus, structured logs
Senior: blue/green or rolling deploys, feature flags, rollback when migration fails.
Live coding, system design, and behavioral
Live coding: flatten a nested dictionary with dot-separated keys.
Common prompt testing recursion and edge cases:
def flatten(d, parent=""):
out = {}
for key, value in d.items():
full_key = f"{parent}.{key}" if parent else key
if isinstance(value, dict):
out.update(flatten(value, full_key))
else:
out[full_key] = value
return out
print(flatten({"a": 1, "b": {"c": 2, "d": {"e": 3}}}))
# {'a': 1, 'b.c': 2, 'b.d.e': 3}Clarify with interviewer:
- Are values only dicts and scalars?
- What about lists of dicts?
- Mutate or return new dict?
Think aloud: base case (scalar), recursive case (dict), string key building.
System design: real-time notification service in Python — what constraints do you mention?
Cover:
- Ingress — HTTP or WebSocket gateway (FastAPI/ASGI)
- Fan-out — asyncio for I/O; processes if CPU-heavy formatting
- Queue — Redis/RabbitMQ for durability
- Workers — Celery consumers for email/push providers
- Storage — Postgres for preferences, idempotency keys
- Scale — horizontal API replicas; sticky sessions only if needed for WS
Python-specific: acknowledge GIL—do not promise single-process multi-core CPU; partition work across processes or specialized services.
Compare architecture patterns in full stack developer interview questions.
Final-week checklist and one behavioral tip?
Technical drills:
- Explain mutable default, GIL, and asyncio vs threading without notes
- Write retry decorator and flatten dict on whiteboard
- Walk through Django N+1 fix with
select_related/prefetch_related - Defend Django vs FastAPI for a JD-specific scenario
- One pytest fixture + parametrized test from memory
- Sketch FastAPI + worker queue deploy diagram
Cross-prep:
- SQL interviews for JOIN/window practice
- Data science interviews if role blends ML
- Git interviews for PR workflow stories
Behavioral (STAR): Prepare one story where you fixed a production Python incident—bad deploy, runaway query, memory leak, or async blocking—with metrics (latency, error rate, query count).
A strong close:
I rehearse framework depth for the JD, core Python traps aloud, and three STAR stories tied to services I actually shipped—not slides of syntax trivia.
Pattern cheat sheet (quick reference)
| Topic | Remember |
|---|---|
| Mutable default | Use None sentinel |
| Large data | Generators, chunked reads |
| CPU parallel | multiprocessing / native code |
| I/O concurrent | asyncio or threads |
| Django N+1 | select_related, prefetch_related |
| API contracts | Pydantic / DRF serializers |
| Tests | pytest fixtures + parametrize |
| Deploy | Container + migrations + health check |
References
Official Python documentation
- Python 3 documentation
- asyncio — Asynchronous I/O
- dataclasses
- Django documentation
- FastAPI documentation
On-site prep
- Full stack developer interviews
- Django interview questions for experienced developers
- Kafka interview questions
- Data science interview questions
- SQL technical interview questions
- Node.js developer interviews
- Python yield
- Python kwargs and args
- Python try except
- Flask SQLAlchemy
- Create a Python package
- Git interview questions
- Interview Questions category
Summary
Python developer interviews connect language fundamentals to framework and production choices—mutable defaults, generator memory, GIL-aware concurrency, ORM query counts, and async discipline on FastAPI services. Answer aloud and compare your structure to each section. Pair with SQL and full stack prep when the role spans the whole stack.

