Questions
15 of 18
1Why is using a mutable default argument (e.g., `def f(x=[])`) considered a common pitfall?
2What is the purpose of the `nonlocal` keyword, and how does it differ from `global`?
3How does Python's `for` loop differ conceptually from a C-style `for` loop?
4How does structural pattern matching (`match`/`case`, introduced in Python 3.10) differ from a chain of `if`/`elif` statements?
5What are first-class functions, and how does Python's treatment of functions as objects enable higher-order functions?
6What is the purpose of the `else` clause on `for` and `while` loops, and when does it execute?
7How would you implement memoization for a recursive function, and what tradeoffs exist between manual caching and `functools.lru_cache`?
8What is the difference between positional, keyword, default, `*args`, and `**kwargs` parameters?
9Explain Python's LEGB rule for variable scope resolution.
10How does Python's `for` loop differ conceptually from a C-style `for` loop?
11What are first-class functions, and how does Python's treatment of functions as objects enable higher-order functions?
12How would you implement memoization for a recursive function, and what tradeoffs exist between manual caching and `functools.lru_cache`?
13What is the purpose of the `nonlocal` keyword, and how does it differ from `global`?
14What is the difference between positional, keyword, default, `*args`, and `**kwargs` parameters?
15Why is using a mutable default argument (e.g., `def f(x=[])`) considered a common pitfall?
16How does structural pattern matching (`match`/`case`, introduced in Python 3.10) differ from a chain of `if`/`elif` statements?
17What is the purpose of the `else` clause on `for` and `while` loops, and when does it execute?
18Explain Python's LEGB rule for variable scope resolution.
15 / 18

Why is using a mutable default argument (e.g., `def f(x=[])`) considered a common pitfall?

Difficulty: 4/10
Functions & Scope, Default Arguments, Function Definition Time vs Call Time

Defaults are evaluated once, at function definition time

The default expression is evaluated once, when the def statement executes, and the resulting object is stored on the function object (in defaults and kwdefaults). Every call that omits the argument receives that same object. For immutable defaults (None, numbers, strings, tuples) that is harmless. For a mutable default such as a list, dict or set, mutations persist between calls, producing state that leaks across callers and sometimes across requests or users.

javascript

The same root cause applies to non-obvious 'dynamic' defaults such as datetime.now(), time.time(), uuid4() or an object constructor: they are computed once at import time, so every call sees the same timestamp or ID. The fix is the None-sentinel pattern (or a private sentinel object when None is itself a valid argument), creating the value inside the function body. In dataclasses use field(default_factory=...); the dataclass machinery refuses mutable defaults, raising ValueError for list, dict or set in older versions, and since 3.11 for any unhashable default.

Trade-offs: the shared default can be used deliberately as a cheap cache or counter, but that is hidden global state and hard to test or reset; functools.lru_cache or an explicit object is clearer. The behavior is a design choice - evaluating at definition time makes defaults cheap and predictable - and late-bound default proposals (such as PEP 671) have been discussed, so check their status rather than assuming. For prevention, enable the flake8-bugbear rule B006 or the equivalent ruff rule so CI catches it. Common mistake: believing the bug only affects lists; any mutated default object, including dicts and custom class instances, behaves the same way.

Scenario Questions

0-2 years experience

  1. 1What does this print: def add(x, l=[]): l.append(x); return l, followed by add(1) and add(2)? Why?
  2. 2How do you fix a function with a list default, and why is None the usual replacement value?

2-5 years experience

  1. 1A function is declared as def log(msg, ts=datetime.now()) and every log line shows the same timestamp. Explain why and fix it.
  2. 2Is a mutable default ever intentional? Give a legitimate use and say what you'd use instead in production code.

5-8 years experience

  1. 1A dataclass with items: list = [] raises ValueError. Explain why, show the fix with field(default_factory=list), and mention how behavior differs across Python versions.
  2. 2A threaded web service has a function with a default dict used as scratch space, and occasionally one user sees another user's data. How would you diagnose and fix it?

8+ years experience

  1. 1How would you detect mutable defaults at scale (inspecting __defaults__, AST checks, ruff or bugbear rule B006) and handle intentional exceptions in a monorepo?
  2. 2Why didn't Python's designers evaluate defaults on every call? Discuss the trade-offs, the sentinel-object pattern for when None is a valid value, and the status of late-bound default proposals.

Follow-up Questions

  • How can you inspect a function's default values at runtime?
  • How would you prevent this bug across a large codebase automatically?
Share

Share via WhatsApp, X, Facebook, LinkedIn or copy link. Open Graph preview enabled.