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
Top comments (0)