Python Interview Questions for Mid-Level 2026
162 applications per offer, 2026 average.
Advertisement
You’ve done the beginner grind. You can write Python, ship features, fix bugs, and explain what a list comprehension is without sweating. But mid-level Python interviews in 2026 are a different beast: they test whether you can think like someone who owns code in production.
Companies are not just asking “What is a decorator?” anymore. They want to know how you debug slow APIs, design clean modules, write safe concurrent code, test properly, and talk through tradeoffs like a grown-up engineer.
If you are interviewing for Python roles at places like Spotify, Stripe, Revolut, Shopify, Datadog, Booking.com, Zalando, or fast-growing startups, expect the bar to sit somewhere between “solid developer” and “future senior.”
In the US, mid-level Python developers often see salaries around $105k to $145k, with higher ranges at companies like Meta, Google, Netflix, and Stripe. In Europe, you might see €55k to €85k in cities like Berlin, Amsterdam, Dublin, Madrid, and Paris, with senior-leaning mid-level roles hitting €90k to €110k at stronger tech firms.
So let’s get you ready.
What Mid-Level Python Interviews Actually Test in 2026#
A mid-level Python interview is rarely about memorizing syntax. You are expected to know the language, but the real signal is how you reason.
Most interviews test five things:
-
Core Python knowledge
- Data structures
- Functions and scope
- Classes and inheritance
- Iterators and generators
- Exceptions
- Type hints
-
Practical engineering judgment
- When to write simple code
- When abstraction helps
- How to avoid clever messes
- How to make code readable for the next person
-
Production awareness
- Logging
- Error handling
- Performance
- Memory use
- Testing
- Observability
-
Framework knowledge
- Django
- FastAPI
- Flask
- SQLAlchemy
- Celery
- Pytest
-
System thinking
- APIs
- Databases
- Queues
- Caching
- Background jobs
- Async work
At mid-level, your answers should sound like you have been burned by real code before. Not dramatic, just practical.
A junior answer says: “I would use a dictionary because lookup is O(1).”
A mid-level answer says: “I would use a dictionary if the data fits in memory and keys are stable. If this grows large or needs persistence, I’d probably move it to Redis or a database index.”
That second answer is what interviewers want.
Core Python Interview Questions for Mid-Level Developers#
1. What are Python’s main built-in data structures, and when would you use each?
You should be able to explain:
list: ordered, mutable, good for sequencestuple: ordered, immutable, good for fixed recordsdict: key-value lookup, great for mappingsset: unique values, membership checksdeque: fast appends and pops from both endsheapq: priority queuesCounter: counting itemsdefaultdict: cleaner default values
A good answer sounds like this:
“I’d use a list for ordered data I need to iterate over, a dict for fast lookup by key, and a set when I care about uniqueness or membership. If I’m building a queue, I’d avoid popping from the front of a list because that is O(n). I’d use collections.deque instead.”
That last sentence matters. It shows you know performance without being annoying about it.
2. What is the difference between is and ==?
== checks value equality. is checks object identity.
Example:
a = [1, 2, 3]
b = [1, 2, 3]
a == b # True
a is b # False
Use is for singleton checks:
if value is None:
...
Do not write:
if value == None:
...
The interviewer may ask about small integers or string interning. You can say Python may reuse some immutable objects internally, but you should not depend on that behavior in application code.
3. Explain mutable default arguments.
This is a classic mid-level trap.
Bad code:
def add_item(item, items=[]):
items.append(item)
return items
The default list is created once when the function is defined, not every time it is called. So calls share the same list.
Better:
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
A strong answer includes when this behavior might be intentional, such as caching, but says you would normally avoid it because it surprises people.
4. What are decorators, and when would you use them?
A decorator wraps a function or class to add behavior.
Common uses:
- Logging
- Authentication checks
- Timing
- Caching
- Retry logic
- Validation
Example:
import time
from functools import wraps
def timing(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
print(f"{func.__name__} took {time.time() - start:.2f}s")
return result
return wrapper
Mention functools.wraps. That is a nice mid-level signal because it preserves function metadata.
A strong answer also says decorators can make code harder to debug if overused. Keep them simple and obvious.
5. What are generators, and why use them?
Generators produce values lazily. They are useful when you do not want to load everything into memory.
Example:
def read_lines(path):
with open(path) as f:
for line in f:
yield line.strip()
Use cases:
- Processing large files
- Streaming data
- Pipelines
- Infinite sequences
- Memory-sensitive tasks
You can say: “A generator helps when I want iteration without storing the full collection. For example, reading a 5GB log file line by line.”
That is better than just saying “it uses yield.”
6. What is the difference between iterator and iterable?
An iterable is anything you can loop over. An iterator is the object that actually returns the next value.
- Iterable has
__iter__ - Iterator has
__iter__and__next__
Example:
numbers = [1, 2, 3]
iterator = iter(numbers)
next(iterator)
A list is iterable but not itself an iterator. A generator is both.
Python OOP Questions You Should Expect#
7. How does inheritance work in Python?
Python supports single and multiple inheritance. A class can inherit attributes and methods from a parent class.
Example:
class Animal:
def speak(self):
return "sound"
class Dog(Animal):
def speak(self):
return "bark"
Mid-level answer: explain that inheritance is useful when there is a real “is-a” relationship. Otherwise, composition may be cleaner.
Good line:
“I try not to build deep inheritance trees in business code. Composition is often easier to test and change.”
Interviewers love that because it sounds like someone who has maintained messy code.
8. What is MRO in Python?
MRO means Method Resolution Order. It is the order Python uses to search for methods in a class hierarchy.
You can inspect it:
MyClass.__mro__
or:
help(MyClass)
Python uses the C3 linearization algorithm. You do not need to explain the algorithm in detail unless asked.
Say this:
“MRO matters most with multiple inheritance. If two parent classes define the same method, Python follows the MRO to decide which method gets called.”
9. What are @staticmethod, @classmethod, and instance methods?
Instance methods receive self. They operate on object state.
Class methods receive cls. They often act as alternative constructors or work with class-level data.
Static methods receive neither self nor cls. They are namespaced helper functions.
Example:
class User:
def __init__(self, email):
self.email = email
@classmethod
def from_dict(cls, data):
return cls(data["email"])
@staticmethod
def normalize_email(email):
return email.strip().lower()
A good answer includes judgment:
“If the method needs instance data, use an instance method. If it creates or modifies class-level behavior, use a class method. If it is just related utility logic, static method can be okay, though sometimes a module-level function is clearer.”
Advertisement
Python Performance Interview Questions#
10. How would you make slow Python code faster?
Do not jump straight to “use Cython.” Start with measuring.
Strong answer:
- Reproduce the issue
- Add logging or metrics
- Profile with
cProfile,py-spy, orline_profiler - Check database queries
- Check network calls
- Improve algorithms
- Reduce unnecessary allocations
- Cache where safe
- Move heavy work to background jobs
- Consider NumPy, Rust, Go, or C extensions only if needed
Mid-level developers know that slow Python is often not Python’s fault. It is usually bad queries, too many API calls, missing indexes, or loading too much data.
For example:
“If a Django endpoint is slow, I’d check SQL queries first with Django Debug Toolbar or logging. N+1 queries are very common.”
That answer hits reality.
11. What is Big O, and what should Python developers know?
You should know common costs:
- List append: usually O(1)
- List insert at front: O(n)
- Dict lookup: average O(1)
- Set membership: average O(1)
- Sorting: O(n log n)
- Nested loop over same collection: often O(n²)
Interviewers may ask you to optimize code like this:
result = []
for user_id in user_ids:
if user_id in active_user_ids:
result.append(user_id)
If active_user_ids is a list, membership is O(n). Convert it to a set:
active = set(active_user_ids)
result = [user_id for user_id in user_ids if user_id in active]
Explain the tradeoff:
“This uses extra memory for the set, but makes lookup much faster for large inputs.”
12. What is the GIL?
The GIL, or Global Interpreter Lock, allows only one thread to execute Python bytecode at a time in CPython.
Practical impact:
- Threads can help with I/O-bound tasks
- Threads usually do not speed up CPU-bound Python code
- Multiprocessing can help CPU-bound work
- Async can help high-concurrency I/O
- Native extensions may release the GIL
Good answer:
“If I’m calling APIs or waiting on database responses, threads can still help because most time is spent waiting. If I’m doing CPU-heavy image processing or data crunching, I’d look at multiprocessing, NumPy, or moving that work outside the request path.”
In 2026, you may also get asked about free-threaded Python builds. You can say CPython has been moving toward optional no-GIL builds, but many production stacks still need compatibility testing before depending on that.
That is a safe, current answer.
13. When would you use multiprocessing?
Use multiprocessing for CPU-bound tasks where separate processes can run in parallel.
Examples:
- Image processing
- Large file transformations
- Batch calculations
- Data parsing
- ML preprocessing
Watch out for:
- Serialization cost
- Memory overhead
- Process startup time
- Shared state complexity
- Debugging difficulty
Good phrase:
“I’d use multiprocessing when the work is large enough to justify the overhead and can be split into independent chunks.”
Async Python Interview Questions#
14. What problem does asyncio solve?
asyncio helps manage many I/O-bound tasks concurrently using an event loop.
Good examples:
- Calling many APIs
- WebSocket connections
- Async web servers
- Chat systems
- Crawlers
- Queue consumers
Basic example:
import asyncio
import httpx
async def fetch(url):
async with httpx.AsyncClient() as client:
response = await client.get(url)
return response.text
async def main():
pages = await asyncio.gather(
fetch("https://example.com"),
fetch("https://example.org"),
)
The key point:
“Async does not make CPU code faster. It helps when tasks spend time waiting.”
15. What is the difference between concurrency and parallelism?
Concurrency means handling multiple tasks in overlapping time. Parallelism means doing multiple tasks at the same exact time.
A nice answer:
“Async Python gives concurrency on one thread. Multiprocessing gives parallelism across CPU cores.”
Simple. Clean. Interviewer happy.
16. What mistakes happen in async Python?
Common mistakes:
- Forgetting
await - Blocking the event loop with CPU work
- Using sync libraries inside async code
- Creating too many tasks without limits
- Not handling cancellation
- Not setting timeouts
- Sharing mutable state badly
Example bad idea:
time.sleep(5)
Inside async code, use:
await asyncio.sleep(5)
For external calls, set timeouts. Mid-level developers mention timeouts because production systems die slowly without them.
Django, FastAPI, and Web Interview Questions#
17. Django vs FastAPI: when would you choose each?
Django is great when you want batteries included:
- ORM
- Admin panel
- Authentication
- Forms
- Migrations
- Security defaults
FastAPI is great when you want:
- API-first services
- Async support
- Pydantic validation
- OpenAPI docs
- Lightweight structure
- Fast development for microservices
Good answer:
“I’d pick Django for a product with admin workflows, relational data, and built-in auth needs. I’d pick FastAPI for a focused API service where request validation and OpenAPI docs matter a lot.”
Mention company style if useful. Instagram has famously used Django at massive scale. FastAPI is common across startups and API-heavy teams because it is quick and clean.
18. How do you prevent N+1 queries in Django?
N+1 happens when code does one query for a list, then one extra query per item.
Example bad pattern:
posts = Post.objects.all()
for post in posts:
print(post.author.name)
Fix with:
posts = Post.objects.select_related("author").all()
Use:
select_relatedfor foreign key and one-to-oneprefetch_relatedfor many-to-many and reverse relationships
Also mention:
- Add indexes where needed
- Inspect queries
- Avoid loading unused fields
- Paginate large lists
19. How does FastAPI validation work?
FastAPI uses type hints and Pydantic models to validate and serialize data.
Example:
from pydantic import BaseModel
class UserCreate(BaseModel):
email: str
age: int
FastAPI can:
- Validate request bodies
- Generate OpenAPI docs
- Serialize responses
- Return clear validation errors
In 2026, many teams are using Pydantic v2. You do not need to recite every change, but you should know validation models are central to FastAPI.
Testing Questions for Mid-Level Python Roles#
20. How do you test Python code?
A strong answer mentions layers:
- Unit tests for isolated logic
- Integration tests for database and service interactions
- API tests for endpoints
- Contract tests where services depend on each other
- End-to-end tests for critical flows
Tools:
pytestunittestcoverage.pyfactory_boyfreezegunresponsespytest-mockhypothesis
Good answer:
“I prefer testing behavior, not implementation details. If I refactor internal code and tests break even though behavior is the same, the tests may be too tightly coupled.”
That is a very mid-level thing to say.
21. What makes a good unit test?
Good unit tests are:
- Fast
- Deterministic
- Easy to read
- Focused on one behavior
- Clear when they fail
Example structure:
def test_discount_applies_for_premium_user():
user = User(plan="premium")
price = calculate_price(user, base_price=100)
assert price == 80
Avoid tests that need five mocks and a prayer. If a unit test is painful to write, your code may be too coupled.
22. How do you mock external services?
You can use mocks or fake services. For HTTP calls, tools like responses or respx are common.
Good answer:
“I mock external APIs in unit tests so tests are fast and stable. For integration tests, I may use a sandbox environment or a local fake service if the contract matters.”
Also mention that you do not want tests failing because Stripe, Twilio, or SendGrid had a temporary issue.
Advertisement
Database and API Design Questions#
23. How do you design a REST API endpoint?
Talk through:
- Resource naming
- HTTP methods
- Request validation
- Authentication
- Authorization
- Pagination
- Filtering and sorting
- Status codes
- Error format
- Rate limits
- Idempotency where needed
Example:
GET /api/users?page=2&status=active
POST /api/users
GET /api/users/\{id\}
PATCH /api/users/\{id\}
DELETE /api/users/\{id\}
For payments or order creation, mention idempotency keys. Companies like Stripe care deeply about this, and many interviewers love hearing it.
24. What status codes should you know?
Know the practical ones:
200: OK201: Created204: No Content400: Bad Request401: Not authenticated403: Authenticated but not allowed404: Not found409: Conflict422: Validation error, common in FastAPI429: Rate limited500: Server error
A mid-level answer includes consistency:
“I’d make sure errors have a consistent structure so frontend and API clients can handle them cleanly.”
25. How would you handle database transactions?
Use transactions when multiple database changes must succeed or fail together.
Example:
from django.db import transaction
with transaction.atomic():
order = Order.objects.create(user=user)
Payment.objects.create(order=order, amount=total)
Mention:
- Keep transactions short
- Avoid slow network calls inside transactions
- Handle retries for deadlocks where appropriate
- Think about isolation levels for sensitive workflows
Good phrase:
“I would not call an external payment provider inside a long database transaction if I can avoid it. I’d separate the steps and use clear state transitions.”
Error Handling and Logging Questions#
26. How do you handle exceptions in Python?
Use specific exceptions where possible.
Bad:
try:
process()
except Exception:
pass
Better:
try:
process()
except PaymentDeclined as exc:
logger.info("Payment declined", extra={"reason": str(exc)})
raise
Good answer:
“I avoid swallowing exceptions unless I have a clear fallback. If I catch an exception, I either handle it, add context and re-raise it, or return a controlled error.”
27. What should you log?
Log events that help debug production issues:
- Request IDs
- User or account IDs where safe
- Job IDs
- External service response codes
- Timing
- State changes
- Error context
Avoid:
- Passwords
- API keys
- Full credit card data
- Sensitive personal data
- Huge payloads
You can say:
“I want logs to answer what happened, to whom, and where, without leaking private data.”
That is a clean production-minded answer.
Clean Code and Architecture Questions#
28. How do you structure a Python project?
For a small FastAPI service:
app/
main.py
api/
models/
schemas/
services/
repositories/
tests/
For Django, you may organize by apps:
users/
orders/
payments/
notifications/
Good answer:
“I prefer structure that matches the domain and keeps business logic out of views or route handlers. Controllers should be thin. The important logic should be testable without running the whole web app.”
29. What are type hints good for?
Type hints help:
- Improve readability
- Catch errors earlier
- Improve editor support
- Document expected inputs and outputs
- Support tools like mypy and pyright
Example:
def calculate_total(prices: list[float]) -> float:
return sum(prices)
Good answer:
“Type hints do not make Python statically typed at runtime by default, but they help teams maintain larger codebases.”
Mention that type hints are very common now in mid-level and senior Python roles, especially with FastAPI.
30. How do you review Python code?
Strong review checklist:
- Is the code clear?
- Are edge cases handled?
- Are tests meaningful?
- Are database queries reasonable?
- Are errors handled safely?
- Is logging useful?
- Is there unnecessary abstraction?
- Is performance acceptable?
- Is security considered?
- Will this be maintainable in six months?
A good interview answer:
“I try to review for correctness first, then readability and maintainability. I avoid style nitpicks if tooling can handle them.”
Behavioral Questions for Mid-Level Python Interviews#
31. Tell me about a production bug you fixed.
Use this format:
- Situation
- Impact
- Investigation
- Fix
- Prevention
Example answer:
“We had an API endpoint timing out during peak traffic. I checked logs and saw response time spiking only on one list endpoint. Query logging showed an N+1 issue that loaded customer records inside a loop. I fixed it with select_related, added a regression test, and added basic query count monitoring for that view.”
That sounds real. It has impact, debugging, fix, and prevention.
32. Tell me about a technical disagreement.
Do not say everyone was wrong and you saved the company. That sounds exhausting.
Better:
“We disagreed about adding a shared abstraction for multiple integrations. I felt the abstraction was too early because only two integrations existed and their behavior was different. I suggested keeping shared helper functions first, then revisiting after the third integration. We did that, and the final abstraction was much cleaner.”
This shows judgment and teamwork.
33. How do you handle unclear requirements?
Good answer:
“I ask questions, write down assumptions, and try to create a small version first. If the risk is high, I confirm behavior with product or stakeholders before building too much.”
Mid-level developers are expected to protect the team from wasted work.
Coding Exercise Questions You Might See#
34. Find the first non-repeating character.
from collections import Counter
def first_unique_char(text: str) -> str | None:
counts = Counter(text)
for char in text:
if counts[char] == 1:
return char
return None
Explain:
- First pass counts characters
- Second pass preserves order
- Time is O(n)
- Space is O(k), where k is unique characters
35. Merge intervals.
def merge_intervals(intervals: list[tuple[int, int]]) -> list[tuple[int, int]]:
if not intervals:
return []
intervals.sort()
merged = [intervals[0]]
for start, end in intervals[1:]:
last_start, last_end = merged[-1]
if start ≤ last_end:
merged[-1] = (last_start, max(last_end, end))
else:
merged.append((start, end))
return merged
Explain sorting cost: O(n log n). The scan is O(n).
36. Rate limiter design question.
You may be asked: “How would you rate limit API requests?”
Simple answer:
- Use Redis
- Store count per user or IP
- Set expiration window
- Return
429when limit is exceeded
Example design:
key = rate_limit:\{user_id\}:\{minute\}
INCR key
EXPIRE key 60
Better answer includes tradeoffs:
“A fixed window is simple but can allow bursts at boundaries. A sliding window or token bucket is smoother but more complex.”
That is mid-level gold.
Questions You Should Ask the Interviewer#
Do not end with “No questions from me.” Ask smart, practical questions.
Try these:
- “What does success look like for this role after six months?”
- “What are the biggest technical problems the Python team is dealing with?”
- “How much of the work is new feature development vs maintenance?”
- “What Python frameworks are used most here?”
- “How do you handle testing and code review?”
- “Are engineers expected to be on call?”
- “What is the deployment process like?”
- “How does the team measure production health?”
- “What would make someone struggle in this role?”
- “What salary range is budgeted for this position?”
That last one is fair. If a US company is hiring a mid-level Python developer for $95k, and your target is $130k, you need to know early. In Europe, if the role is €60k in Amsterdam or Dublin, ask about total compensation, remote policy, pension, bonus, and equity.
How to Prepare in 7 Days#
If your interview is soon, here is a practical plan.
Day 1: Core Python
Review:
- Lists, dicts, sets, tuples
- Mutability
- Scope
- Decorators
- Generators
- Exceptions
Write small examples by hand.
Day 2: Algorithms
Practice:
- Hash maps
- Two pointers
- Sorting
- Stacks and queues
- Basic recursion
- String parsing
Do not grind 200 LeetCode questions. For mid-level Python roles, quality beats panic.
Day 3: Web Frameworks
Review the framework in the job description.
For Django:
- ORM
- Migrations
- Middleware
- Query optimization
- Auth
- Transactions
For FastAPI:
- Pydantic
- Dependency injection
- Async endpoints
- Response models
- OpenAPI docs
Day 4: Databases and APIs
Review:
- Indexes
- Joins
- Transactions
- Pagination
- REST status codes
- Idempotency
- Caching
Day 5: Testing
Practice writing tests with pytest.
Focus on:
- Fixtures
- Mocking
- Parametrize
- Testing exceptions
- Testing APIs
- Coverage basics
Day 6: System Design Lite
Prepare for small design questions:
- URL shortener
- Rate limiter
- Background email worker
- File upload service
- Notification system
- Analytics event collector
At mid-level, they do not expect Staff Engineer architecture. They expect sane tradeoffs.
Day 7: Stories and Resume
Prepare five stories:
- Bug you fixed
- Feature you shipped
- Performance improvement
- Conflict or disagreement
- Time you learned something fast
Tie each story to business impact. “Reduced endpoint response time from 2.8s to 400ms” is much better than “optimized API.”
Final Checklist Before the Interview#
Use this quick checklist the night before:
- Can you explain your last project clearly?
- Can you talk about one hard bug?
- Can you write Python without autocomplete?
- Can you explain decorators and generators?
- Can you discuss async vs threads vs multiprocessing?
- Can you spot N+1 queries?
- Can you write a few
pytesttests? - Can you explain one API design?
- Can you ask about salary without sounding awkward?
- Can you explain tradeoffs instead of pretending every choice is obvious?
That last point is the big one.
Mid-level interviews are not about having a perfect answer. They are about showing that you can make reasonable decisions, communicate clearly, and keep production code healthy.
If you want one easy win before applying, run your resume through a checker and make sure it actually matches Python jobs before a recruiter sees it. Try the free JobRise ATS checker here: https://jobrise.io/en/free-ats-checker/
Advertisement
Advertisement
Send this to whoever has the interview this week.
Keep reading
Australia 482 Visa Jobs for Software Engineers: How It Works
A practical guide to the Australia 482 visa for software engineers, covering sponsorship, occupation lists, and the application timeline.
Backend Developer Jobs in Finland with Visa Sponsorship
Your guide to landing backend developer jobs in Finland with visa sponsorship, covering the market, salaries, and a clear application checklist.
Business Analyst Jobs in Australia with Visa Sponsorship
Find out how to land business analyst jobs in Australia with visa sponsorship, including salary ranges and application tips for 2026.
Advertisement
Advertisement