Defaults are evaluated once
You already know default parameters: def greet(name="friend"). Here is the detail Python for Beginners skipped, and it causes real bugs: the default value is created once, when the def line runs, not on every call.
For numbers and strings that is harmless. For a mutable value like a list or dict, it means every call that uses the default shares the same object:
def add_item(item, bucket=[]): bucket.append(item) return bucket
Call it twice without passing a bucket and the second call finds the first call's item still sitting in the list. This trap genuinely ships to production, where a shared default list quietly leaks one request's data into the next, and it is one of the most common Python interview questions. Run the next example to see it happen.
Code exercise · python
Run this program and look closely at the second line. We never passed a list, yet "apple" is already in it.
The fix: a None sentinel
The standard pattern is to default to None (an immutable placeholder) and create the fresh list inside the function body, which runs on every call:
def add_item(item, bucket=None): if bucket is None: bucket = [] bucket.append(item) return bucket
Now each default call gets its own new list. Remember the rule as: never use [], {}, or any mutable object as a default value. Every experienced Python interviewer asks about this.
Code exercise · python
Your turn. Fix log_event so each call without a target list gets a FRESH list. Use the None sentinel pattern. The output should show two independent single-item lists.
Quiz
Why is def f(x, seen=set()) dangerous?
Quiz
Which default values are safe to write directly in a def line?