Python

  • By Language
  • 40 questions

What this round is for

Python rounds tend to open with data structures and quickly move to the things that reveal experience: mutable defaults, the GIL, generators, and whether you know what a decorator actually is underneath the syntax.

The questions below are ordered roughly that way. Where a question has a famous trap attached, the answer explains why it behaves that way, because the reason is what interviewers are listening for.

The questions

Answer each one out loud before you open it. An answer you have read is not an answer you can give under pressure, which is the only kind that counts.

Q1 What is the difference between a list and a tuple?

Show the answer Hide the answer

A list is mutable; a tuple is not, which is why a tuple can be a dictionary key.

Immutability also makes a tuple hashable and slightly cheaper. Use a tuple for a fixed group of related values and a list for a collection that changes.

What it is really testing. Whether you mention hashability. 'One has brackets' is the answer of someone who has not needed the distinction.

Q2 Why is a mutable default argument a bug?

Show the answer Hide the answer

The default is evaluated once when the function is defined, so every call shares the same object.

Appending to a default list accumulates across calls. The fix is a None default and creating the list inside the function.

What it is really testing. Whether you can explain why rather than reciting the rule. The same issue affects mutable class attributes.

Q3 What is the difference between is and ==?

Show the answer Hide the answer

is compares identity - the same object; == compares value.

Use is only for None, True and False. Small integers and short strings are cached, so is sometimes appears to work for values and then stops when the value grows.

What it is really testing. Whether you know the caching makes it unreliable. That is why 'it worked in the REPL' is not evidence.

Q4 How does Python handle variable assignment?

Show the answer Hide the answer

Names are bound to objects; assignment never copies.

Two names can refer to one list, so mutating through either is visible through both. Python has names and objects rather than variables containing values.

What it is really testing. Whether you can explain aliasing. Most surprising mutation bugs come from this.

Q5 What is a shallow versus a deep copy?

Show the answer Hide the answer

A shallow copy duplicates the container and shares what is inside; a deep copy recurses.

Slicing and copy() are shallow, so nested lists remain shared. copy.deepcopy handles the rest at some cost.

What it is really testing. Whether you know when shallow is insufficient. The bug only appears with nesting.

Q6 What is a list comprehension and when should you not use one?

Show the answer Hide the answer

An expression that builds a collection in one line - and not when it stops being readable.

They are faster than a loop with append and read as a description of the result. Two for clauses plus a condition is the point at which a plain loop is clearer.

What it is really testing. Whether you have a limit. Readability was the goal, not brevity.

Q7 What is a generator?

Show the answer Hide the answer

A function using yield that produces values lazily, one at a time.

Only one item is in memory at once, so a pipeline over a huge file runs in constant memory. The trade is that it can be consumed only once and has no length.

What it is really testing. Whether you name the memory benefit and the one-shot cost.

Q8 What is the difference between a generator and a list comprehension?

Show the answer Hide the answer

Square brackets build the whole list; parentheses create a generator that produces on demand.

Summing a generator expression over ten million items uses almost no memory; the list version builds all ten million first.

What it is really testing. Whether you know the syntax difference is the memory difference.

Q9 What are *args and **kwargs?

Show the answer Hide the answer

They collect extra positional and keyword arguments into a tuple and a dictionary.

They are also used at the call site to unpack, which is how decorators forward arguments without knowing the signature.

What it is really testing. Whether you know they work in both directions.

Q10 What is a decorator?

Show the answer Hide the answer

A function that wraps another to add behaviour, applied with the @ syntax.

It is just a function taking a function and returning one. functools.wraps preserves the original name and docstring, and omitting it breaks introspection and documentation tools.

What it is really testing. Whether you mention functools.wraps. It is the detail that separates use from understanding.

Q11 What is a context manager?

Show the answer Hide the answer

An object with __enter__ and __exit__ used with the with statement to guarantee cleanup.

The same guarantee as try/finally with none of the ceremony and no way to forget. contextlib.contextmanager builds one from a generator.

What it is really testing. Whether you can name a use beyond files - a lock, a transaction, a timer.

Q12 What is the GIL and what does it mean for you?

Show the answer Hide the answer

A lock allowing one thread to execute Python bytecode at a time, so threads give no CPU parallelism.

It is released during I/O, so threads help for network and disk work. CPU-bound work needs multiprocessing or a library that releases it internally.

What it is really testing. Whether you can decide between threads and processes for a given workload.

Q13 When would you use asyncio over threads?

Show the answer Hide the answer

For large numbers of concurrent I/O operations, where the overhead of a thread each is too high.

asyncio is cooperative - a task must await to yield control, so one blocking call stalls everything. Threads are pre-emptive and more forgiving of blocking code.

What it is really testing. Whether you know a blocking call inside async code defeats the point.

Q14 What is the difference between a module and a package?

Show the answer Hide the answer

A module is a file; a package is a directory of modules.

Imports are cached after the first execution, and the search path starts with the script's own directory - which is why naming a file random.py shadows the standard library.

What it is really testing. Whether you know about shadowing. It produces errors that point nowhere useful.

Q15 What causes a circular import and how do you fix it?

Show the answer Hide the answer

Two modules importing each other, so one gets a half-initialised module.

The symptom is an attribute that exists in the file but not at import time. The real fix is almost never a clever import - it is that something belongs in a third module.

What it is really testing. Whether you know the real fix is structural rather than an import trick.

Q16 What is the difference between __str__ and __repr__?

Show the answer Hide the answer

__str__ is for users, __repr__ for developers and should ideally be unambiguous.

repr is what you see in a debugger and in a list of objects. Defining only __str__ leaves repr as the default, which tells you nothing useful in a traceback.

What it is really testing. Whether you define both. A default repr in a traceback tells you nothing.

Q17 What are dunder methods?

Show the answer Hide the answer

Special methods with double underscores that hook into language operators and protocols.

Defining __len__, __iter__ or __eq__ makes your object work with built-in functions and syntax. That is how Python's duck typing is implemented.

What it is really testing. Whether you know they are how duck typing is implemented.

Q18 What is the difference between a classmethod and a staticmethod?

Show the answer Hide the answer

A classmethod receives the class as its first argument; a staticmethod receives nothing special.

classmethod is the right choice for alternative constructors, because it works correctly with subclasses. staticmethod is a plain function living in a class for organisation.

What it is really testing. Whether you know classmethod is the right one for alternative constructors.

Q19 What is a property?

Show the answer Hide the answer

A method accessed like an attribute, used to add computation or validation without changing callers.

It means you can start with a plain attribute and add logic later with no change at any call site - which is why Python code does not have reflexive getters and setters.

What it is really testing. Whether you know it means Python does not need getters and setters by default.

Q20 How does Python handle multiple inheritance?

Show the answer Hide the answer

Through the method resolution order, computed by the C3 linearisation.

super() follows that order rather than going straight to a parent, which is what makes cooperative multiple inheritance work and why calling a parent directly can skip classes.

What it is really testing. Whether you can explain the MRO rather than just naming it.

Q21 What does super() actually do?

Show the answer Hide the answer

It delegates to the next class in the method resolution order, not necessarily the direct parent.

In a diamond hierarchy that distinction matters. Calling the parent class by name instead breaks the chain and can run an initialiser twice or not at all.

What it is really testing. Whether you know it is not simply the parent class. That distinction matters in a diamond.

Q22 What is duck typing?

Show the answer Hide the answer

Behaviour is determined by what methods an object has, not by its declared type.

It is why a test double can be any object with the right methods. The cost is that a missing method surfaces at run time, which is why Python's testing culture is strong.

What it is really testing. Whether you name the testing consequence. It is why Python culture tests heavily.

Q23 What are type hints and are they enforced?

Show the answer Hide the answer

Annotations describing expected types - and no, the interpreter ignores them entirely.

They are checked by a separate tool such as mypy and power editor completion. They are documentation that a tool can verify, not a run-time guarantee.

What it is really testing. Whether you know they are not enforced at run time.

Q24 What is the difference between @staticmethod and a module-level function?

Show the answer Hide the answer

Almost nothing functionally - the staticmethod is namespaced inside the class.

Choose it when the function is conceptually part of the class and does not need its state. A module function is usually simpler and easier to test.

What it is really testing. Whether you can justify the choice rather than treating it as arbitrary.

Q25 What does the with statement guarantee?

Show the answer Hide the answer

That __exit__ runs when the block ends, including when it raises.

That is the whole value: resource release cannot be skipped by an early return or an exception. Whenever you acquire something that must be released, you are writing a context manager.

What it is really testing. Whether you can generalise beyond files to locks and transactions.

Q26 What is the difference between append and extend?

Show the answer Hide the answer

append adds one item; extend adds each item of an iterable.

Appending a list nests it; extending flattens one level. Passing a string to extend adds every character, which is a classic surprise.

What it is really testing. Whether you know extend on a string adds characters. It is a classic surprise.

Q27 Why is a set faster than a list for membership checks?

Show the answer Hide the answer

Hashing gives constant-time lookup; a list must scan.

Swapping a list for a set is the single most common fix for a Python loop that is unexpectedly slow, and it is usually a one-word change.

What it is really testing. Whether you reach for it when a loop is slow. It is the most common easy win.

Q28 What does the collections module give you?

Show the answer Hide the answer

Counter for tallying, defaultdict for grouping, deque for a double-ended queue, namedtuple for light records.

Each replaces several lines of hand-written code that is easy to get subtly wrong. Reading the module once is one of the highest-return hours in the language.

What it is really testing. Whether you have read the module. Most candidates have reimplemented Counter by hand.

Q29 What is the walrus operator for?

Show the answer Hide the answer

Assigning inside an expression, so a value can be computed and tested in one step.

It avoids computing something twice or writing an extra line before a while loop. It was added late and deliberately, with syntax that cannot be confused with equality.

What it is really testing. Whether you know it avoids computing a value twice.

Q30 How do you handle exceptions well in Python?

Show the answer Hide the answer

Catch the narrowest class that fits, never bare except, and never swallow silently.

Bare except catches keyboard interrupts and system exit too. An empty except pass is how a program loses errors it needed to report.

What it is really testing. Whether you know bare except catches keyboard interrupts too.

Q31 What is EAFP and why does Python prefer it?

Show the answer Hide the answer

Easier to ask forgiveness than permission - attempt the operation and handle failure.

Checking first leaves a gap between the check and the use, which matters in concurrent code. Attempting has no gap, and the exception path is cheap when it is rare.

What it is really testing. Whether you know the concurrency argument, not just the style preference.

Q32 What is the difference between an iterator and an iterable?

Show the answer Hide the answer

An iterable can produce an iterator; an iterator produces values and is consumed.

A list is iterable and can be looped many times. Its iterator is exhausted after one pass, which is why a generator cannot be reused.

What it is really testing. Whether you can explain why a generator cannot be looped twice.

Q33 What does a virtual environment do and why does it matter?

Show the answer Hide the answer

It isolates a project's packages so two projects can use different versions.

Installing globally guarantees a conflict eventually, and conflicts are painful to untangle. Pin versions in a file and treat the environment as disposable.

What it is really testing. Whether you treat environments as disposable rather than maintained.

Q34 What is the difference between a .py script and a module being imported?

Show the answer Hide the answer

__name__ is '__main__' when run directly and the module name when imported.

That is why the if __name__ guard exists - it lets a file be both a runnable script and an importable module without executing the script part on import.

What it is really testing. Whether you can explain the __name__ guard rather than copying it.

Q35 How do you read a large file without loading it into memory?

Show the answer Hide the answer

Iterate the file object directly, which yields one line at a time.

Combined with a generator pipeline, a multi-gigabyte file can be processed in constant memory. Calling read() or readlines() defeats this entirely.

What it is really testing. Whether you know read() defeats the whole point.

Q36 What is pickling and when should you avoid it?

Show the answer Hide the answer

Serialising a Python object to bytes - and you should never unpickle untrusted data.

Unpickling can execute arbitrary code, so it is a remote code execution vulnerability if the source is not trusted. It is also version-fragile across Python releases.

What it is really testing. Whether you know it is a remote code execution risk, not just a format.

Q37 What is a dataclass?

Show the answer Hide the answer

A decorator that generates init, repr and equality from annotated fields.

It removes the boilerplate from classes that mostly carry data, and the generated equality is correct, which hand-written versions frequently are not.

What it is really testing. Whether you know the generated equality is correct, which hand-written ones often are not.

Q38 How do you test Python code effectively?

Show the answer Hide the answer

With pytest - a plain function and an assert, no class or special assertion methods required.

The low ceremony matters more here than in a compiled language, because there is no compiler to catch a misspelled attribute. In a dynamic language the test suite does that job.

What it is really testing. Whether you connect low ceremony to the absence of a compiler.

Q39 What is the difference between sort and sorted?

Show the answer Hide the answer

sort mutates a list in place and returns None; sorted returns a new sorted list from any iterable.

Assigning the result of sort is a common error that silently produces None. sorted also works on sets, dicts and generators.

What it is really testing. Whether you know sort returns None. Assigning its result is a frequent bug.

Q40 What makes code Pythonic?

Show the answer Hide the answer

Choosing the obvious, readable construction over the clever one.

Explicit over implicit, flat over nested, one obvious way to do it. Nearly every convention serves the person reading the code in a year, who may well be you.

What it is really testing. Whether you can articulate a principle. This is often the closing question.

Two things worth doing in the room

  • When you are asked about performance, say whether the work is I/O-bound or CPU-bound before proposing anything. That single distinction decides threads versus processes and shows you are not guessing.
  • If a question is about a gotcha, give the rule and then the mechanism. 'Defaults are evaluated once at definition time' is worth more than 'do not use mutable defaults'.