Programming Languages

Python interview questions & practice path

Decorators, generators, the GIL, and data structures under the hood. Learn what interviewers probe, drill the questions until answers come fast, then prove it in a scored mock, all in one Python path inside Round Zero.

  • Concept lessons that explain the why, not just the answer
  • Practice questions with adaptive follow-ups and flashcards
  • A scored mock with evidence quoted from your own answers

Sample Python questions

What a strong answer covers, and the mistakes interviewers watch for. The scored path drills every one with live follow-ups.

What happens when you use a mutable object like a list as a default argument value in a function, and why?

easy

A strong answer covers

  • Default argument values are evaluated once at function definition time, not on each call, so the same list object is shared across every call that relies on the default
  • Mutating that shared default (e.g. appending) causes state to leak between calls, a classic source of surprising bugs
  • The idiomatic fix is to default to None and create a fresh list inside the body: def f(x, acc=None): if acc is None: acc = []
  • Ties back to Python binding default values to the function object at def time, stored in func.__defaults__

Common mistakes

  • Claiming defaults are re-evaluated on every call, which is the opposite of the real behavior
  • Suggesting you should just avoid lists entirely rather than using the None sentinel pattern
  • Confusing this with variable scope rather than the timing of default-value evaluation

What is the difference between the `is` operator and the `==` operator? When would they give different results?

easy

A strong answer covers

  • == compares values by calling __eq__, while is compares object identity (whether both names point to the same object, effectively id() equality)
  • They diverge when two distinct objects are equal by value: e.g. two separate lists [1,2] == [1,2] is True but is is False
  • Small-int caching (-5 to 256) and string interning can make is appear True for equal values, which is a CPython implementation detail and should not be relied on
  • The correct idiom is x is None for singletons like None, True, False; use == for value comparison

Common mistakes

  • Using is to compare integers or strings and assuming it always works because of caching
  • Saying is compares values or that == compares identity, reversing the two
  • Not recognizing None/True/False are singletons where is is the correct check

Explain the difference between a generator and a list. When would you choose a generator, and what are the tradeoffs?

medium

A strong answer covers

  • A list materializes all elements in memory at once; a generator produces values lazily one at a time via the iterator protocol (__next__), holding only current state
  • Generators give O(1)-ish memory for large or infinite sequences and enable pipelines and streaming, using yield or generator expressions (x for x in ...)
  • Tradeoffs: generators are single-pass and exhaustible, have no len() or indexing, and cannot be reused once consumed
  • Good fit for large files, data pipelines, or when you only iterate once; a list is better when you need random access, multiple passes, or the length

Common mistakes

  • Saying generators are always faster, when for small reused collections a list can be faster and simpler
  • Forgetting a generator is exhausted after one full iteration and trying to loop over it twice
  • Confusing generator functions (with yield) and generator expressions, or conflating them with regular functions that return lists

What is a decorator? Write one that logs the arguments and return value of any function it wraps.

medium

A strong answer covers

  • A decorator is a callable that takes a function and returns a replacement (usually a wrapper), applied with @decorator syntax as syntactic sugar for f = decorator(f)
  • The wrapper should accept *args and **kwargs so it works on any signature, call the original, and return its result
  • Use functools.wraps on the wrapper to preserve the original function's __name__, __doc__, and metadata
  • Strong answers mention decorators with arguments (an extra layer of nesting) and real uses like caching, timing, auth, and retry

Common mistakes

  • Writing a wrapper with a fixed signature instead of *args/**kwargs, breaking it for other functions
  • Omitting functools.wraps, which silently loses the wrapped function's identity and docstring
  • Forgetting to return the wrapper's result, so the decorated function returns None

What is the Global Interpreter Lock (GIL), and how does it affect your choice between threading, multiprocessing, and asyncio?

hard

A strong answer covers

  • The GIL is a CPython mutex that lets only one thread execute Python bytecode at a time, so threads cannot run CPU-bound Python code in true parallel on multiple cores
  • Threads still help I/O-bound work because the GIL is released during blocking I/O and many C extensions; asyncio handles high-concurrency I/O in a single thread via an event loop and cooperative await
  • For CPU-bound parallelism use multiprocessing (or a ProcessPoolExecutor), which runs separate interpreters/processes each with its own GIL, at the cost of IPC and memory overhead
  • Nuance: the GIL is a CPython implementation detail (not in the language spec), and recent work on free-threaded / no-GIL CPython (PEP 703) is changing this landscape

Common mistakes

  • Claiming the GIL makes threads useless for everything, ignoring that I/O-bound workloads benefit
  • Recommending threading for CPU-bound number crunching in pure Python
  • Treating the GIL as a language-level guarantee rather than a CPython implementation detail

Explain the difference between assignment, a shallow copy, and a deep copy for a nested data structure like a list of lists.

hard

A strong answer covers

  • Assignment (b = a) binds a new name to the same object; mutations through either name are visible through both because there is only one object
  • A shallow copy (copy.copy, list(a), a[:]) creates a new outer object but its elements are references to the same inner objects, so mutating a nested list affects both copies
  • A deep copy (copy.deepcopy) recursively copies nested objects so the result is fully independent, and it handles shared references and cycles via a memo table
  • Strong answers note deep copy is more expensive, that immutable inner elements make the shallow/deep distinction moot, and that custom classes can control copying via __copy__/__deepcopy__

Common mistakes

  • Believing list(a) or a[:] fully clones nested structures, then being surprised nested mutations leak
  • Not distinguishing that mutating an outer element vs a nested element behaves differently under a shallow copy
  • Reaching for deepcopy everywhere, ignoring its cost and that it is unnecessary for flat or immutable data

How Python answers are scored

Language Fundamentals and Data Model

40%

Correctly explains mutability, references vs copies, hashability, name binding, and how core types behave. Strong performers reason about the CPython data model (identity vs equality, __hash__/__eq__, iterator protocol) and predict evaluation results accurately rather than guessing.

Idiomatic and Correct Code

35%

Writes Pythonic, readable code using comprehensions, generators, context managers, unpacking, and standard-library tools appropriately. Strong performers avoid common traps (mutable defaults, late-binding closures), handle edge cases, and choose the right built-in data structure for the task.

Runtime, Concurrency, and Performance

25%

Explains the GIL and its implications for threads vs processes vs async, reasons about time and space complexity of built-ins, and knows when to reach for generators, sets, or vectorized tools. Strong performers connect language behavior to real performance and memory outcomes.

Role tracks that include Python

Related Programming Languages skills

All skills →

No spam. Unsubscribe anytime.

Ready to master Python?

Sign up free. Your Python path includes lessons, drills, flashcards, and a scored mock with feedback on what to fix.

  • Concept lessons plus practice questions
  • Flashcards for spaced repetition
  • A scored mock with evidence quotes

Questions & answers

What Python interview questions should I practice?
Start with the core areas Python interviewers probe: What happens when you use a mutable object like a list as a default argument value in a function, and why; What is the difference between the `is` operator and the `==` operator? When would they give different results; Explain the difference between a generator and a list. When would you choose a generator, and what are the tradeoffs. This page outlines strong answers and common mistakes, and the scored path drills each one with follow-ups.
Is the Python practice free?
Yes, you can start a Python path free inside Round Zero. It generates lessons, practice questions, flashcards, and a scored mock. Sign up to unlock the full drills and your evidence-backed scorecard.
How is this different from a Python question list?
A static list gives you questions with no feedback. Round Zero runs a live scored practice that probes your actual answers, rotates difficulty, and tells you exactly what to fix, grounded in a Python rubric.
How should I prepare for a Python interview?
Learn the concepts, drill the questions until answers come fast, then prove it in a scored mock. Round Zero sequences all three so you know you are ready, not just that you read about Python.
How is a Python answer scored?
Python answers are scored on language fundamentals and data model, idiomatic and correct code, runtime, concurrency, and performance, with evidence quoted from what you actually said, so feedback is specific instead of generic praise.