A subtle and dangerous Python bug many developers encounter is this:
Your function works once, then starts behaving strangely on later calls.
Data keeps growing.
Values persist unexpectedly.
And you never intended that.
This happens a lot in:
- API handlers
- Utility functions
- Data processing scripts
- Django / Flask apps
- Caching logic
- Logging helpers
It feels random, but it is not.
Let’s fix it step by step.
The Problem
Suppose you write this:
def add_item(item, items=[]):
items.append(item)
return items
print(add_item("apple"))
print(add_item("banana"))
Expected Output
["apple"]
["banana"]
Actual Output
["apple"]
["apple", "banana"]
Very confusing.
Why This Happens
In Python, default arguments are evaluated only once.
This line:
items=[]
runs only when the function is defined—not each time it is called.
So the same list is reused across all calls.
What’s Really Happening
This code:
def add_item(item, items=[]):
behaves like:
shared_list = []
def add_item(item, items=shared_list):
Every call uses the same list.
That is why values keep accumulating.
Step 1: Fix Using None
Correct solution:
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
Output Now
["apple"]
["banana"]
Now each call gets a fresh list.
Why This Fix Works
Because None is safe and immutable.
Each function call creates a new list only when needed.
Real Example
Bad:
def create_user(name, roles=[]):
roles.append("user")
return {"name": name, "roles": roles}
Correct:
def create_user(name, roles=None):
if roles is None:
roles = []
roles.append("user")
return {"name": name, "roles": roles}
Another Case
Bad:
def update_config(config={}):
config["debug"] = True
return config
Correct:
def update_config(config=None):
if config is None:
config = {}
config["debug"] = True
return config
Quick Debug Rule
If data keeps "remembering" old values:
Ask yourself:
Am I using a mutable default argument?
Final Thoughts
This is not a bug—it is Python behavior.
Remember:
- Default arguments run once
- Lists and dicts are mutable
- Mutable defaults create shared state
- Always use
Noneas default
This small fix prevents big bugs.
Your Turn
Have you seen this bug before?
Most Python developers remember the first time it happened.
Peace,
Emily Idioms