Find the bug · Easy
Fix the Mutable Default Argument
Easy Find the bug Most asked
collect_evens(nums) returns the even numbers of nums in order. It takes an optional result list so callers can append into an existing list.
The first call works. Later calls return numbers from earlier calls too. Find the bug and fix it without removing the optional parameter.
Example 1
Input: collect_evens([1, 2, 3, 4]) Output: [2, 4]
Example 2
Input: collect_evens([6, 7]) # called next Output: [6] Explanation: The buggy version returns [2, 4, 6].
The buggy code
def collect_evens(nums: list[int], result: list[int] = []) -> list[int]:
for x in nums:
if x % 2 == 0:
result.append(x)
return result
Hints
Hint 1
When is a default argument value created in Python: on each call, or once?
Find and fix the bug
Loading the editor… (JavaScript is required to run code in your browser.)
Solution and explanation
Show the bug and the fix
Time O(n) · Space O(n)
The bug: default values are evaluated once, when the def statement runs, not on every call. result: list[int] = [] creates a single list shared by every call that omits the argument, so each call appends to the evens from all previous calls.
The fix: use None as the sentinel and create a new list inside the function: if result is None: result = []. The same trap applies to {} and set() defaults, and to dataclass fields (use field(default_factory=list)).
Fixed version
def collect_evens(nums: list[int], result: list[int] | None = None) -> list[int]:
if result is None:
result = [] # a new list on every call
for x in nums:
if x % 2 == 0:
result.append(x)
return result
Common mistakes
- "Fixing" it by clearing the list at the start of the function, which breaks callers who pass their own list.
More Code Clinic: Find the Bug problems
- Fix the Binary Search · Easy
- Fix the Two Sum Hash Map · Easy
- Fix the Longest Substring Without Repeats · Medium
- Fix Merge Intervals · Medium
- Fix the Substring Check · Easy
- Fix the Median (JavaScript Sort) · Easy