Python mutable default pitfall (or feature)

General mutable default issue
def buggy(items=[]):  # Mutable default - DANGEROUS
    items.append(1)
    return items

print(buggy())  # [1]
print(buggy())  # [1, 1] - Unexpected!

# OUTPUT
# [1]
# [1, 1]

See this deep dive as well Common Gotchas — The Hitchhiker's Guide to Python (archived)

Problem

Classes decorated with dataclass reject mutable default values (lists, dicts, sets) with error: field args is not allowed: use default_factory

Cause

Python evaluates default arguments once at definition time, not per-instance. Mutable defaults become shared across all instances, causing side-effect bugs.

Solution

Use field(default_factory=list) pattern:

from dataclasses import dataclass, field

@dataclass
class Example:
    # WRONG: immutable_field: list = []  # Shared across instances!

    # CORRECT: Creates new list per instance
    mutable_field: list = field(default_factory=list)
    dict_field: dict = field(default_factory=dict)
    custom_obj: MyClass = field(default_factory=MyClass)
Implementation Note

default_factory accepts any callable that returns a new instance. For custom types, pass the class itself or a function that instantiates it.

Another example

From Python Cookbook book, page 223 ```python

def spam(a, b=[]): ... print(b) ... return b

x = spam(1) x [] x.append(99) x.append('Yow!') x [99, 'Yow!'] spam(1) # Modified list gets returned! [99, 'Yow!']