Home βΊ Problems βΊ Mutable default argument trap
Mutable default argument trap
π§ Predict the output Topic: functions Difficulty: medium Free
What this problem practises
Function bugs are mostly about names and values: positional argument order, default parameters evaluated once at definition time, local versus global scope, and the implicit None returned whenever a function has no return.
This is an output-prediction problem: read the snippet carefully and write down exactly what it prints before anything runs. These questions are interview staples because they test whether you know the language rules, or merely recognise their syntax.
Difficulty: medium β expect to hold two interacting rules in your head at once, such as a boundary combined with a mutation.
The challenge
The code runs in PyDebugβs in-browser compiler. Open the problem, run the snippet, watch the exact error or output, and keep iterating until it is right. Signed-in solves count toward XP and your daily streak.
The snippet
The interactive editor pre-fills exactly this code β read it, then submit your prediction:
def add_item(item, items=[]):
items.append(item)
return items
print(add_item("A"))
print(add_item("B"))Understand the rule
Default arguments are evaluated once, when Python creates the function, not every time the function is called. A list used as a default therefore becomes shared state between calls. The function appears to remember old values even though the caller did not pass them explicitly.
How to trace it
- Look at the function definition and identify which default objects are mutable.
- Call the function once and note that the default list is modified.
- Call it again without an argument and observe that the same list is reused.
- Replace the default list with None, then create a fresh list inside the function.
Common wrong fixes
- Assuming every default expression is re-created at the call site.
- Fixing the symptom with list.clear(), which still leaves shared state.
- Using a mutable default intentionally without documenting that it is a cache.
Rule to remember
Use None as the default sentinel for a list or dictionary, then allocate the mutable object inside the function. This keeps each call independent.
π§© Learning path: Functions
Problem 12 of 12 in this path. Work them in order β each one builds on the rule before it.
β Modifying a variable before it's assigned locallyπ Path complete β review it β
πΌ Learning path: Interview Practice
Problem 1 of 16 in this path. Work them in order β each one builds on the rule before it.
β© Path overviewNext in path: Class variable shared across instances β
More functions problems
Keep going
- Output-prediction strategies β how to predict tricky snippets without running them.
- Browse every functions problem in this topic.
- Common Python errors and what they actually mean, plus the Python glossary for any term used on this page.