Python interviews vary enormously by role and company. A data science interview looks very different from a backend API role, and a senior engineer interview looks nothing like a junior screen. This guide covers 50 questions across four seniority levels, with notes on what a strong answer looks like for each.
Junior Python developer (0–2 years)
These questions test core language knowledge and basic problem-solving. Candidates shouldn't be expected to know everything, but should be able to reason through problems out loud.
1. What is the difference between a list and a tuple in Python? Look for: Lists are mutable, tuples are immutable. Tuples are slightly faster and used for fixed data structures. Bonus: mention that tuples can be dictionary keys, lists cannot.
2. Explain what a Python decorator is.
Look for: A function that wraps another function, modifying its behaviour without changing the original. Strong candidates give an example (@login_required, @cache).
3. What does *args and **kwargs mean?
Look for: *args collects positional arguments into a tuple, **kwargs collects keyword arguments into a dict. Strong candidates explain when to use each.
4. What is list comprehension? Give an example.
Look for: [x**2 for x in range(10) if x % 2 == 0]. Faster and more readable than a for loop for simple transformations.
5. What is the difference between == and is in Python?
Look for: == tests value equality, is tests identity (same object in memory). Common gotcha: a = [1,2]; b = [1,2]; a == b is True, a is b is False.
6. How does Python manage memory? Look for: Reference counting plus a cyclic garbage collector. Objects are freed when their reference count hits zero. Bonus: mention that CPython has a GIL.
7. What is a generator? How is it different from a list?
Look for: Generators yield values lazily — they don't compute the next value until it's requested. Better for large datasets. yield vs return.
8. What is the purpose of __init__ in a Python class?
Look for: It's the constructor method, called when an instance is created. Used to set initial state.
9. Explain the difference between append() and extend() on a list.
Look for: append(x) adds x as a single element. extend(iterable) adds each element of the iterable. [1,2].append([3,4]) → [1,2,[3,4]] vs [1,2].extend([3,4]) → [1,2,3,4].
10. What happens when you open a file with with open(...) as f:?
Look for: Context manager — the file is automatically closed when the block exits, even if an exception is raised.
Mid-level Python developer (2–5 years)
These questions test deeper language knowledge, common patterns, and practical experience with real codebases.
11. Explain Python's GIL. What are its implications for concurrency? Look for: The Global Interpreter Lock prevents multiple Python threads from executing bytecode simultaneously. For CPU-bound tasks, use multiprocessing. For I/O-bound tasks, threading or async still helps.
12. What is the difference between threading and multiprocessing in Python?
Look for: threading shares memory but is limited by GIL for CPU-bound work. multiprocessing spawns separate processes with separate memory — bypasses GIL but has higher overhead for IPC.
13. Explain async/await in Python. When would you use it?
Look for: Coroutines for I/O-bound concurrency without threads. await suspends the coroutine until the awaited task completes, allowing the event loop to run other tasks. Use for database calls, HTTP requests, file I/O.
14. What is a context manager and how do you implement one?
Look for: Implements __enter__ and __exit__ methods, or use @contextlib.contextmanager with yield. Used for setup/teardown: file handles, database connections, locks.
15. What are dataclasses and when would you use them over a regular class?
Look for: @dataclass auto-generates __init__, __repr__, __eq__. Use when the class is primarily a data container. Cleaner than NamedTuple for mutable data.
16. How does Python's functools.lru_cache work?
Look for: Memoises function results based on arguments. Stores results in a dict. maxsize controls cache size; maxsize=None caches everything. Only works with hashable arguments.
17. Explain the difference between deepcopy and copy.
Look for: copy creates a shallow copy — nested objects share references. deepcopy recursively copies all nested objects. Important when objects contain mutable sub-objects.
18. What is duck typing and how does Python use it? Look for: "If it walks like a duck and quacks like a duck, it's a duck." Python checks for method/attribute presence at runtime rather than type. The basis for polymorphism without inheritance.
19. How would you handle a large CSV file that doesn't fit in memory?
Look for: Read in chunks with pandas.read_csv(chunksize=...) or use Python's built-in csv reader iteratively. Generators. dask for larger datasets.
20. What is the purpose of __slots__ in a class?
Look for: Prevents creation of __dict__ on instances, reducing memory usage. Useful for classes with many instances. Also slightly faster attribute access.
21. How would you implement a singleton in Python?
Look for: Module-level variable (simplest). __new__ override. Metaclass. Decorator. Strong candidates mention thread safety.
22. What is monkey patching? When is it useful and when is it dangerous? Look for: Dynamically modifying a class or module at runtime. Useful in tests (mocking). Dangerous in production — hard to track, breaks encapsulation.
23. Explain Python's method resolution order (MRO).
Look for: C3 linearisation algorithm. Used in multiple inheritance to determine which method to call. ClassName.__mro__ shows the order. Diamond problem.
24. What are metaclasses?
Look for: Classes are instances of metaclasses. type is the default metaclass. Used for class-level behaviour: auto-registering subclasses, enforcing interfaces, ORM magic.
25. How does yield from differ from yield?
Look for: yield from iterable delegates to a sub-generator, passing values and exceptions through. Cleaner than manually iterating and yielding each value.
Senior Python developer (5+ years)
These questions test architectural thinking, performance awareness, and experience with production systems.
26. How would you design a rate limiter in Python? Look for: Token bucket or sliding window algorithm. Redis for distributed rate limiting. Thread-safe implementation. Decorators for API-level application.
27. Explain how you'd profile and optimise a slow Python application.
Look for: cProfile / line_profiler to identify bottlenecks. memory_profiler for memory issues. Fix: algorithmic improvements first, then caching (lru_cache, Redis), then consider Cython/Numba for hot paths.
28. How does asyncio event loop work internally?
Look for: Single-threaded event loop polling for I/O readiness via OS (select, epoll, kqueue). When I/O is ready, the associated coroutine is scheduled to resume. No threads for concurrency — cooperative multitasking.
29. When would you choose SQLAlchemy ORM vs raw SQL? Look for: ORM: rapid development, portability across databases, relationship management. Raw SQL: complex queries, performance-critical paths, when ORM-generated queries are inefficient. Hybrid: ORM for CRUD, raw for analytics.
30. How would you implement background task processing in a Python web app?
Look for: Celery with Redis/RabbitMQ broker for distributed tasks. For simple cases: FastAPI BackgroundTasks. For reliability: persistent queues with at-least-once delivery guarantees.
31. What are the main differences between FastAPI and Django REST Framework? Look for: FastAPI is async-native, faster, auto-generates OpenAPI docs, uses type hints. DRF is mature, more features out-of-box (auth, admin, ORM), larger ecosystem. FastAPI for microservices, DRF for monoliths with complex business logic.
32. How do you handle database migrations in a production Python app? Look for: Alembic (SQLAlchemy) or Django migrations. Blue-green deployments. Adding nullable columns is safe; dropping columns requires multiple deploys. Never delete migration files in production.
33. Explain the CAP theorem and how it affects a distributed Python service you'd design. Look for: Consistency, Availability, Partition tolerance — pick two. Real-world: choose between CP (sacrifice availability during partitions — use for financial data) and AP (sacrifice consistency — use for counters, recommendations). Strong candidates give concrete examples.
34. How would you build a Python service that processes 100,000 events per second? Look for: Kafka consumer. Batch processing. Avoid per-event database writes — batch them. In-process state where safe. Profile and optimise hot paths. Consider multiprocessing for CPU-bound processing.
35. What is your approach to testing a Python application with external dependencies?
Look for: Unit tests mock external calls. Integration tests hit real test instances. Contract tests verify API contracts. pytest-mock / unittest.mock. Fixtures for test data. Clear separation of unit and integration tests.
System design questions
36. Design a URL shortener in Python. Look for: Hash or base62 encode a counter or UUID. Redis for fast lookups. Separate read/write paths. Expiry support. Analytics pipeline (async, don't block redirects).
37. How would you design a job matching system in Python? Look for: Vector embeddings for semantic search (sentence-transformers). Store in a vector database (Qdrant, Pinecone, Weaviate). Hybrid search: semantic + keyword (BM25). Re-ranking with a cross-encoder. For a real-world example of this architecture in production, see What is RAG in Recruiting.
38. Design a Python service to handle webhook delivery with at-least-once semantics. Look for: Persistent queue (Celery + Redis/Postgres). Retry with exponential backoff. Idempotency key on the consumer side. Dead letter queue for permanently failed deliveries.
39. How would you migrate a monolithic Python app to microservices? Look for: Strangler fig pattern. Start with the most isolated modules. Event-driven communication. API gateway. Don't rewrite everything — extract incrementally.
40. Describe how you'd build a caching layer for a high-traffic Python API. Look for: Redis with appropriate TTLs. Cache-aside pattern. Thundering herd prevention (probabilistic early expiration or mutex on cache miss). Cache invalidation strategy. CDN for static responses.
Behavioral questions for Python developers
41. Tell me about a time you improved the performance of a Python application significantly.
42. Describe a bug in Python that took you a long time to debug. What was the cause and how did you find it?
43. Walk me through a technical decision you made that you later regretted. What would you do differently?
44. How do you stay current with the Python ecosystem? What new features in Python 3.12+ are you interested in?
45–50. Role-specific: Adapt these to your team's specific domain (data engineering, web APIs, ML infrastructure, etc.).
Tips for using these questions
For senior roles, skip straight to questions 26–40. Junior and mid-level questions are too easy for senior candidates and will signal that you're not sure what you're looking for.
For technical screens, pick 3–5 questions and go deep rather than covering everything shallowly. A 45-minute technical screen where you only cover 8 questions but really understand the candidate's thinking is far more valuable than covering 25 questions at a surface level.
Writing the JD for this role? Use our Senior Backend Engineer Job Description Template as a starting point — it covers the full role spec, requirements, and hiring process.
Use Rekvo to generate tailored questions for specific candidates. Upload the CV, provide the job description, and Rekvo's AI generates 7 questions specific to that candidate's background — not generic questions from a list like this one.