This one has caught nearly every Python developer at least once, and is arguably the single most common Python "gotcha" interview question:
def add_item(item, basket=[]): # DANGER
basket.append(item)
return basket
add_item("apple") # ["apple"]
add_item("banana") # ["apple", "banana"] — NOT a fresh list!
Default argument values are evaluated once, when the function is defined — not on every call. basket=[] creates one list object, shared across every call that doesn't pass its own basket. The same bug applies to any mutable default: {}, set(), or a custom mutable object. The fix:
def add_item(item, basket=None):
if basket is None:
basket = []
basket.append(item)
return basket
Immutable defaults (0, "", None, a tuple) are completely safe, precisely because there's no way to mutate them in place — every "danger" case involves a mutable default.