Python Interview Questions & Answers (2026 Guide)
Python interviews test three things: language literacy (lists vs tuples, GIL, decorators), practical patterns (comprehensions, generators, async), and problem-solving under pressure. This guide covers 20 questions we've seen candidates hit at Google, Meta, Amazon, and Stripe interviews in the last 12 months. Grouped by difficulty. Skip to your level.
Beginner questions
1. What's the difference between a list and a tuple? Beginner
Lists are mutable, tuples are immutable. Tuples are slightly faster to iterate and can be used as dict keys or set members. Use a tuple when the collection represents a fixed record (coordinates, RGB colors); use a list when you'll add/remove/reorder.
coords = (3, 4) # tuple — immutable
nums = [1, 2, 3] # list — mutable
nums.append(4) # OK
# coords.append(5) # AttributeError
2. Explain list comprehensions and when NOT to use them. Beginner
List comprehensions are [expr for item in iterable if cond] — concise and often faster than the equivalent for-loop. Don't use them when the expression has side effects, when the loop needs multiple statements per iteration, or when nested comprehensions become unreadable (three levels of nesting is usually a bug).
squares = [n * n for n in range(10) if n % 2 == 0]
# [0, 4, 16, 36, 64]
3. What is the GIL and why does it matter? Beginner
The Global Interpreter Lock allows only one thread to execute Python bytecode at a time in CPython. This means multi-threading doesn't help CPU-bound work — use multiprocessing for CPU parallelism or asyncio for I/O parallelism. The GIL is being progressively removed in Python 3.13+ but you should still know it for interviews.
4. What's the difference between is and ==? Beginner
== compares values (calls __eq__). is compares identity (same object in memory). Use is only for None, True, False, and singletons. [1, 2] == [1, 2] is True, but [1, 2] is [1, 2] is False — different list objects with equal contents.
Practice these live, in your voice
MiPrep's practice mode turns your resume into a rehearsed answer set. Talk through the idioms the way top-tier interviewers score.
Download MiPrep 🔒 Interview audio is never stored on our serversIntermediate questions
5. Implement an LRU cache. Intermediate
Use an OrderedDict — O(1) get/put with move_to_end() to track recency. The interviewer wants to see you talk through the tradeoff: OrderedDict is O(1) all operations. Alternative is a doubly-linked list + hash map, same complexity but more code. If they ask 'do it without stdlib,' write the linked-list version.
from collections import OrderedDict
class LRUCache:
def __init__(self, capacity):
self.cache = OrderedDict()
self.capacity = capacity
def get(self, key):
if key not in self.cache:
return -1
self.cache.move_to_end(key)
return self.cache[key]
def put(self, key, value):
if key in self.cache:
self.cache.move_to_end(key)
self.cache[key] = value
if len(self.cache) > self.capacity:
self.cache.popitem(last=False)
6. Explain generators and when to use yield. Intermediate
Generators are lazy iterators — they compute one value at a time on next(), holding local state between calls. Use them when the sequence is huge (memory savings), infinite (Fibonacci), or expensive to compute upfront. yield pauses execution and resumes on next iteration.
def fib():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
g = fib()
for _ in range(10):
print(next(g)) # 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
7. Explain decorators. Intermediate
A decorator is a function that takes a function and returns a modified function. Used for cross-cutting concerns — logging, timing, auth checks, caching. @decorator is syntactic sugar for func = decorator(func). Know about functools.wraps to preserve the decorated function's __name__ and __doc__.
from functools import wraps
import time
def timeit(func):
@wraps(func)
def wrapper(*args, **kwargs):
t = time.time()
result = func(*args, **kwargs)
print(f'{func.__name__} took {time.time() - t:.3f}s')
return result
return wrapper
@timeit
def slow_add(a, b):
time.sleep(1)
return a + b
Advanced questions
8. How does asyncio work under the hood? Advanced
asyncio runs a single-threaded event loop. await suspends the current coroutine and returns control to the loop, which schedules other ready coroutines. When the awaited I/O completes, the loop resumes the suspended coroutine. It's cooperative — one coroutine hogging CPU blocks everything. Use asyncio.to_thread() to offload CPU work.
9. Design a concurrent rate limiter. Advanced
Token bucket algorithm: refill N tokens per second up to a max, each request consumes 1 token, reject if bucket empty. For distributed rate limits, use Redis atomic INCR with expiry. Discuss thread safety: use asyncio.Lock or a sync primitive. Discuss fairness: FIFO queue vs random rejection.
import asyncio, time
class TokenBucket:
def __init__(self, rate, capacity):
self.rate = rate
self.capacity = capacity
self.tokens = capacity
self.updated = time.monotonic()
self.lock = asyncio.Lock()
async def acquire(self):
async with self.lock:
now = time.monotonic()
self.tokens = min(self.capacity, self.tokens + (now - self.updated) * self.rate)
self.updated = now
if self.tokens < 1:
return False
self.tokens -= 1
return True
10. What are Python's __slots__ and when to use them? Advanced
__slots__ declares a fixed set of attributes on a class, replacing the per-instance __dict__. Saves ~40% memory per instance and slightly speeds attribute access. Use when creating millions of instances of the same class (e.g., graph nodes, price ticks). Cost: no dynamic attribute assignment.
Common mistakes candidates make
- Writing
def f(x=[]):— mutable default arguments are shared across calls. UseNoneand initialize inside. - Confusing
isand==for value comparison (see Q6). - Using threads for CPU-bound work — GIL negates parallelism. Use multiprocessing.
- Overusing
global— a code-smell for interviewers. Refactor to return values. - Forgetting to
awaitin async functions — silently returns a coroutine object, not the result.
Study strategy
Two-week plan: Week 1, drill 10 easy Python idioms per day on LeetCode (comprehensions, generators, dict/set operations). Week 2, do 3-4 medium LeetCode problems per day, always in Python, always writing the O(n) discussion aloud. Do at least 2 timed mock interviews before your real one — timing pressure changes how you think.
Do timed mocks with MiPrep before the real thing
Upload your resume and target job description. MiPrep generates a rehearsed answer set in your voice from your own projects — so mock interviews sound like real ones.
Get MiPrep — free 🔒 Interview audio is never stored on our servers