Python Interview Questions and Answers: 30 Theory Questions
Thirty Python interview questions with the answers interviewers expect: the GIL, how dicts work, generators, decorators, is vs ==, mutable defaults, memory.
- Course: Python study plan
- Module: Interview idioms
- Kind: Lesson
- Reading time: 25 min
- Runtime: CPython 3.11
What are the most common Python interview questions?
The most common Python interview questions ask for a mechanism: what the GIL is, how a dict works, is versus ==, mutable versus immutable types, why a mutable default argument is shared, what a generator, a decorator and a context manager do, how arguments are passed and how memory is managed. A strong answer gives the definition, the one consequence that matters, then stops.
Lesson
Every Python interview has a theory section, and its questions have barely changed in a decade: what the GIL is, how a dict works, what a generator does, why a mutable default is wrong, the difference between is and ==. This lesson is the drill: thirty questions, each with the answer an interviewer wants to hear — the definition first, the one consequence that matters, then a stop so the follow-up can come — and a pointer to the module that teaches it in depth. Read it twice a week before interviews. A Python answer is expected to name a mechanism: not "lists are slow to search" but "in on a list is a linear scan; a set hashes".
The language and its objects
- What does "everything is an object" mean in practice? Every value — ints, functions, classes, modules — is a heap object with a type and a reference count; a variable is a name bound to one. Consequences: assignment copies nothing, functions are passed as values, and
type(x)is itself an object. (Modules 1, 19)
- Mutable versus immutable? An immutable object's value cannot change after creation (int, float, str, tuple, frozenset, bytes); a mutable one can (list, dict, set, bytearray, most instances). Immutables are hashable by default and safe to share; a "change" to one is a new object. (2, 6)
isversus==?iscompares identity (the same object);==compares value through__eq__. Useisonly forNone,True,Falseand sentinels;x is 5works by the small-int cache and is a bug. (2, 19)
- How are arguments passed? By assignment: the parameter is bound to the same object the caller passed ("pass by object reference"). Mutating the object is visible to the caller; rebinding the parameter is not. (4)
- Why is a mutable default argument a bug? Defaults are evaluated once at
deftime and stored on the function, so every call that omits the argument shares the same list. Fix withNoneand create inside. (4, 20)
- What does a closure capture? The variable, by cell, not its value at creation — late binding. Three lambdas made in a loop all see the loop's final value; bind with a default argument or a factory. (16)
//and%with negatives? Floor division rounds towards negative infinity and the remainder takes the divisor's sign:-7 // 2 == -4,-7 % 2 == 1. C and Java truncate instead. (2)
- Why does
0.1 + 0.2 != 0.3? Binary floating point cannot represent those decimals exactly; compare withmath.isclose, format to a fixed precision, or usedecimal/fractionsfor exact arithmetic. (2)
Data structures
- How does a dict work? A hash table:
hash(key)selects a slot in an open-addressed array; equal keys must hash equal; lookups, inserts and deletes are O(1) on average and O(n) in a pathological worst case. Since 3.7 insertion order is guaranteed; the table resizes as it fills. (7, 20)
- What makes an object hashable, and why must lists not be keys? It defines
__hash__consistent with__eq__and its hash never changes; a list's contents can change, so its hash would go stale and the key would be lost. Tuples of hashables and frozensets are the substitutes. (7, 8)
- List versus tuple? Both are ordered sequences; a list is mutable and over-allocates for appends, a tuple is immutable, slightly smaller, hashable when its elements are, and signals "a fixed record". (6)
- The cost of the common operations? List: index O(1), append amortised O(1),
inandinsert(0)O(n); dict and set: O(1) average; sort O(n log n);dequeO(1) at both ends;heapqO(log n) push/pop. A linear operation inside a loop over the same data is the quadratic to look for. (19)
- When do you use a set, a deque, a heap,
bisect? Membership and de-duplication; a queue or sliding window; repeated minimum or top-k; queries on a sorted list or search on a monotonic answer. (7, 13, 20)
- Shallow versus deep copy? A shallow copy (
list(xs),xs[:],copy.copy) is a new container with the same element objects; a deep copy (copy.deepcopy) recursively copies the elements.[[0] * n] * mis m references to one row. (6, 19)
Functions, iteration and classes
- What is a generator, and why use one? A function with
yieldreturns an iterator that runs lazily, one value pernext, keeping its frame between values; it processes streams of any length in constant memory and composes into pipelines. A generator expression is the inline form. (11)
- Iterable versus iterator? An iterable has
__iter__returning an iterator; an iterator has__next__and raisesStopIterationwhen done (and is its own iterable). A list can be iterated many times; an iterator is consumed once. (11)
- What does a decorator do?
@decoabovedef frebindsf = deco(f): a function that takes a function and returns a replacement, usually a wrapper with@functools.wraps. Used for logging, caching, registration, access control. (16)
*argsand**kwargs? Collect extra positional arguments into a tuple and extra keyword arguments into a dict; in a call,*and**unpack them. A wrapper forwards both to be transparent. (4)
- What is a context manager? An object with
__enter__and__exit__used bywith;__exit__runs on every exit including exceptions, so resources are released deterministically.contextlib.contextmanagerwrites one from a generator. (10)
- How does attribute lookup and inheritance work?
obj.xchecks data descriptors on the type, then the instance dict, then the type and its bases in MRO order (C3 linearisation), then__getattr__.super()follows the MRO, which is why cooperative__init__works with multiple inheritance. (8, 9, 16)
@staticmethodversus@classmethod? A static method receives nothing implicit — a function in the class's namespace; a class method receives the class asclsand is the tool for alternative constructors that work in subclasses. (8)
- What is duck typing, and what are protocols and ABCs for? Behaviour is decided by what an object can do, not its type;
typing.Protocolnames a set of methods for static checking, and an ABC (collections.abc) enforces them at run time and can supply mixin methods. (9, 15)
- What does
__slots__do? Replaces the per-instance__dict__with fixed attribute slots: less memory, faster access, no ad-hoc attributes. (19)
- Dataclass versus named tuple versus plain class? A dataclass generates
__init__,__repr__,__eq__(and ordering, hashing, frozenness on request) for a record with named fields; a named tuple is an immutable tuple with names; a plain class is for behaviour beyond a record. (8)
Errors, modules and the run time
try/except/else/finally?exceptcatches;elseruns only when nothing was raised;finallyalways runs. Catch specific exceptions around specific statements;raise ... from echains a cause; exceptions are the control flow for failure, not return codes. (10)
- What is the GIL? A mutex that lets one thread execute bytecode at a time in CPython, released during blocking I/O and by some C extensions. Threads help I/O-bound code, not CPU-bound code; processes give parallelism; asyncio gives single-threaded concurrency for many waits. (17)
- What is a race condition, and how is it fixed? Two threads performing a read-modify-write on shared state between bytecodes —
count += 1is three instructions — so an update is lost. ALockmakes the compound operation atomic; aQueueavoids the sharing. (17)
- How does memory management work? Reference counting frees an object the moment its last reference goes; a generational cycle collector finds reference cycles the counts cannot free;
delremoves a name, not the object. (19)
- What happens on
import? The module is found onsys.path, executed once top to bottom, and cached insys.modules; later imports return the cached object.if __name__ == "__main__":distinguishes running from importing. Circular imports fail when a name is used before the other module finished executing. (12)
- How do you make Python code faster? In order: fix the algorithm, choose the data structure, move the loop into a built-in or a comprehension, batch I/O, then hoist lookups in the profiled hot loop; NumPy for numeric arrays, processes for CPU-bound parallelism. Measure with
cProfileandtimeitbefore and after. (19)
How to use the drill
Read a question, answer aloud in two sentences, then read the answer and note what you left out. The interviewer's follow-up is always "why" or "what happens if" — the mechanism in each answer is what survives that. When an answer references a module number, that module has the code that proves it.
Key takeaways
- Objects, references and mutability explain most language questions; name the mechanism.
- Dicts hash, lists scan, deques and heaps and bisect each answer one shape of question.
- Generators are lazy frames; decorators rebind; context managers guarantee
__exit__; the MRO orders lookup. - Exceptions are for failure, the GIL serialises bytecode, reference counting frees immediately and the collector handles cycles.
- Speed comes from the algorithm and the data structure first, measured before and after.
Common questions
How are arguments passed in Python?
By assignment, often called pass by object reference: the parameter is bound to the same object the caller passed. Mutating that object is visible to the caller; rebinding the parameter to a new object is not.
What is the difference between a list and a tuple in Python?
Both are ordered sequences. A list is mutable and over-allocates so appends are cheap; a tuple is immutable, slightly smaller, hashable when its elements are, and signals a fixed record, which is why a tuple can be a dict key and a list cannot.
What is a generator in Python?
A function containing yield, which returns an iterator that produces values lazily, one per next(), keeping its frame suspended between them. It processes streams of any length in constant memory and composes into pipelines; a generator expression is the inline form.
What is the difference between an iterable and an iterator in Python?
An iterable has __iter__, which returns an iterator; an iterator has __next__, raises StopIteration when exhausted and is its own iterable. A list can be iterated many times, but an iterator is consumed once.
What is the difference between a shallow and a deep copy in Python?
A shallow copy, made by list(xs), xs[:] or copy.copy, is a new container holding the same element objects, so nested lists are shared. copy.deepcopy copies the elements recursively, giving a fully independent structure.
What is the difference between @staticmethod and @classmethod?
A static method receives no implicit first argument; it is a plain function in the class's namespace. A class method receives the class as cls, which makes it the tool for alternative constructors that also work in subclasses.
Exercises
The MRO by hand
Define A, B(A), C(A) and D(B, C), each with a method who() that returns its own letter followed by > and super().who() — except A, which returns "A". Read a class name and print mro <the class names in __mro__> and chain <the result of who() on an instance>.
Input: one class name. Output: two lines.
D
prints
mro D B C A object
chain D>B>C>ALaziness observed
Read k on the first line and integers on the second. Build a generator pipeline over a shared log list: read_all yields each integer after appending read <x>; only_even appends keep <x> and yields evens, or appends drop <x>; squared appends square <x> and yields x * x. Take the first k results with itertools.islice. Print each log line, then result <values or none> and consumed <number of read lines> of <count of integers> — showing that only the integers needed were pulled.
Input: k, then the integers. Output: the log, then two lines.
2
1 2 3 4 5 6
prints
read 1
drop 1
read 2
keep 2
square 2
read 3
drop 3
read 4
keep 4
square 4
result 4 16
consumed 4 of 6In this module: Interview idioms
- The interview template — the round, the file, fast I/O and what is actually judged
- The idiom sheet — the shapes interview problems take and the Python for each
- Pitfalls that fail interviews — the twelve Python mistakes interviewers watch for
- Implement the built-in — a hash map, a dynamic array, an LRU cache and a heap by hand
- Writing clean solutions — structure, names, edges first and the code you can read aloud
- The Python theory drill — thirty questions, thirty answers (this lesson)
- Final checkpoint — Interview idioms
← Writing clean solutions — structure, names, edges first and the code you can read aloud · Final checkpoint — Interview idioms →