Why does my Python default argument keep its old value?
Default arguments are evaluated once, when the function is defined — not on each call. A mutable default like [] is therefore shared by every call. Use None and create the list inside.
Here is the bug:
def add_lesson(name, lessons=[]):
lessons.append(name)
return lessons
add_lesson("Intro") # ['Intro']
add_lesson("Basics") # ['Intro', 'Basics'] <-- not what you wantedThat single list was created once, when def ran. Every call without an explicit argument gets the same list object, complete with everything previous calls put in it.
#The fix
def add_lesson(name, lessons=None):
if lessons is None:
lessons = []
lessons.append(name)
return lessonsNow each call that omits the argument gets a fresh list.
#The rule
Never use a mutable object as a default argument. That means [], {}, set(), and any class instance. Immutable defaults — numbers, strings, tuples, None, True — are all fine, because there is nothing to accumulate.
#Why Python works this way
Evaluating defaults once is what allows this to be fast and predictable:
def search(pattern, flags=re.IGNORECASE):The alternative — re-evaluating on every call — would make every default a hidden function call. The trade-off is this one sharp edge, which is why every Python linter warns about it.