Python interviews test fundamentals more than syntax. The 25 questions below cover the concepts interviewers actually ask: GIL, decorators, generators, async/await, dataclasses, and modern typing. Each answer is structured so you can adapt it to your own voice.
Core concepts (Q1–Q10)
- GIL — the Global Interpreter Lock allows only one thread to execute Python bytecode. CPU-bound work does not parallelise across threads.
- List vs tuple — lists are mutable, tuples are immutable. Tuples can be dict keys.
- Mutable default arguments — classic gotcha. Defaults are evaluated once, at function definition.
- *args / **kwargs — variable positional and keyword arguments.
- List comprehension vs generator expression — comprehensions build a list; generator expressions yield lazily.
- Decorators — functions that wrap other functions. Common for logging, auth, retry.
- Context managers — `with` blocks guarantee cleanup. Implement via `__enter__`/`__exit__` or `@contextmanager`.
- `is` vs `==` — `is` checks identity (same object), `==` checks equality.
- Deep vs shallow copy — `copy.copy()` is shallow (references), `copy.deepcopy()` is recursive.
- `__slots__` — class attribute that declares allowed fields; eliminates `__dict__`, reduces memory.
Intermediate (Q11–Q17)
- Dataclasses — `@dataclass` auto-generates `__init__`, `__repr__`, `__eq__`. Use `frozen=True` for immutability.
- Type hints — PEP 484 annotations. Static analysers catch bugs without runtime cost.
- Async vs threads — async is for I/O-bound concurrency; threads are blocked by the GIL for CPU work.
- `yield from` — delegates to a sub-iterator. Cleaner than `for x in sub: yield x`.
- MRO — Method Resolution Order, computed by C3 linearisation. `Class.__mro__` shows it.
- Descriptors — `__get__` / `__set__` / `__delete__`. `property`, `classmethod`, `staticmethod` are descriptors.
- `__init__.py` vs namespace packages — explicit packages still need `__init__.py`; PEP 420 added namespace packages.
Advanced (Q18–Q25)
- Structural pattern matching — `match`/`case` (3.10+). Supports literal, sequence, mapping, class patterns.
- Protocols — PEP 544 structural typing. `class Sized(Protocol)` is satisfied by anything with `__len__`.
- Coroutines vs generators — both use `yield`, but async coroutines also support `await` and `asyncio` scheduling.
- `asyncio.gather` vs `asyncio.wait` — gather returns coroutine results; wait returns (done, pending) sets.
- `weakref` — holds an object without preventing GC. Useful for caches.
- `__init_subclass__` — hook called whenever a subclass is created. The basis for class registries.
- `concurrent.futures` — high-level thread + process pool. `ProcessPoolExecutor` bypasses the GIL for CPU work.
- `typing.Final` + `@final` — mark names or methods as final; static checkers enforce.
Further reading
Authoritative sources
Related Tutorsbot tutorials
Share:

