Mutable Default Argument
Problem
A reporting service builds one Report per region and appends a summary row to each. The class looks harmless:
class Report:
def __init__(self, title: str, rows: list[dict] = []):
self.title = title
self.rows = rows
def add_row(self, **fields) -> None:
self.rows.append(fields)
def build_daily_reports(day_stats: dict[str, dict]) -> list[Report]:
reports = []
for region, stats in day_stats.items():
r = Report(f"Daily - {region}")
r.add_row(**stats)
reports.append(r)
return reportsSymptom: the eu report contains the us row as well as its own, and after the service has been up for a day every report contains hundreds of rows from other regions and earlier days. Restarting the worker process "fixes" it for a while. Explain what is happening and fix it.
Examples
build_daily_reports({"us": {"orders": 10}, "eu": {"orders": 4}})→ expectedusrows[{"orders": 10}],eurows[{"orders": 4}]. Actual: both reports have rows[{"orders": 10}, {"orders": 4}], andreports[0].rows is reports[1].rowsisTrue.- Calling
build_daily_reportsa second time in the same process → each new report starts with all rows from the previous call already present. Report("x", rows=[{"a": 1}])→ correct, because an explicit list was passed. Only the default is broken, which is why the one test that passed rows explicitly was green.
Hints
- When is the expression
[]in the signature evaluated: every call, or once? - Print
id(r.rows)for two different reports created without passingrows. - Look at
Report.__init__.__defaults__after the first call.
Last reviewed 8 September 2026
Approach · Solution (Python) · Complexity · Follow-ups · Company variations · Tests
The rest of this question — the worked approach, the Python solution with passing tests, complexity, follow-ups and how each company frames it — is part of the guides.
Get the full guide
Pick the company you're interviewing with. Each guide has every question tiered for that loop — one-time purchase, lifetime access.
Also in: Apple, Google, Meta, Microsoft, Netflix
Interviewing at more than one? All 6 guides for $499 · save $395
Not ready to buy? Get the free starter pack — 13 questions with full solutions.