Default Mutable Arguments
ID |
python.default_mutable_arguments |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Python |
Tags |
reliability, suspicious-construct |
Description
Reports parameters with mutable default values ([], {}, set(), list(), dict()). Python evaluates default arguments once at function definition time, so the same mutable object is shared across every call. The first time the function mutates the default, every subsequent call observes the mutation.
def append(item, items=[]): # FLAW
items.append(item)
return items
# After:
# append(1) -> [1]
# append(2) -> [1, 2] (!)
# append(3) -> [1, 2, 3]
def append(item, items=None): # OK
if items is None:
items = []
items.append(item)
return items
Rationale
This is one of the most-cited Python bugs in introductory courses, and yet still slips through review when a function is added quickly. Static detection catches it before the side effect ever fires.