Never Use [ ] as a Default Argument in Python...

NeuralNineAbout 3 min readMay 29, 2026Watch original
THE SUMMARYAI-generated

Key Concepts

  • Mutable Objects: Objects whose state can be modified after creation (e.g., list, dict, set, and custom class instances).
  • Default Argument Evaluation: In Python, default arguments are evaluated only once at the time the function is defined, not every time the function is called.
  • Function Signature: The part of the function definition where parameters and their default values are declared.

The Problem: Mutable Default Arguments

The core issue is that when a mutable object (like an empty list []) is used as a default argument, Python creates that object once during the function definition. Subsequent calls to the function reuse the exact same object in memory.

Example of the Bug:

def create_player(name, inventory=[]):
    inventory.append("starter weapon")
    return {"name": name, "inventory": inventory}

When calling create_player("Alice") and then create_player("Bob"), both players share the same inventory list. Because the list is created at definition time, the "starter weapon" persists across calls, leading to unexpected data accumulation. This behavior applies equally to dictionaries, sets, and custom class instances.


The Solution: The "None" Pattern

To ensure that a new object is created for every function call, you must initialize the mutable object inside the function body.

Step-by-Step Implementation:

  1. Set the default to None: Change the function signature to use None as the default value.
  2. Check for None inside the function: Use an if statement to check if the argument is None.
  3. Initialize inside the function: Create the new list (or other mutable object) only if the check confirms the argument is None.

Corrected Code:

def create_player(name, inventory=None):
    if inventory is None:
        inventory = []
    inventory.append("starter weapon")
    return {"name": name, "inventory": inventory}

Logic: By moving the initialization inside the function, the code executes at call time, ensuring every player gets a fresh, independent list.


Handling External Inputs Safely

If you need to pass an existing list as an argument but want to prevent the function from modifying the original object passed by the user, you should create a copy.

  • Methodology: Use the .copy() method (or list() constructor) inside the function.
  • Why: This prevents "side effects" where the function accidentally modifies the data structure provided by the caller.

Refined Implementation:

def create_player(name, inventory=None):
    if inventory is None:
        inventory = []
    else:
        inventory = inventory.copy()  # Prevents modifying the original list
    inventory.append("starter weapon")
    return {"name": name, "inventory": inventory}

Summary of Key Takeaways

  • Avoid Mutable Defaults: Never use [], {}, or custom objects as default arguments in Python function signatures.
  • Definition vs. Call Time: Remember that default arguments are bound at the moment the function is defined.
  • Use None as a Sentinel: The standard Pythonic way to handle optional mutable arguments is to default them to None and initialize them inside the function body.
  • Defensive Copying: If you expect users to pass their own lists into your function, use .copy() to ensure your function operates on a local version of that data, preserving the integrity of the user's original object.

AI summaries can miss context or contain errors. Check important details against the original video.

Go a little deeper.

Have a question about this video? Load its transcript to open the video chat.