flake8-mutable
flake8-mutable is a linter extension for Flake8 that identifies and flags the use of mutable objects as default arguments in Python function definitions. This helps prevent common and often unexpected bugs where mutations to the default argument persist across function calls. The current version is 1.2.0. The project appears to be stable with infrequent updates, having been last released in 2017.
Common errors
-
M511 - mutable default arg of type List
cause A list (which is a mutable data type) was used as a default argument in a function definition. This causes all calls to the function to share the same list object, leading to unintended side effects when the list is modified.fixChange the default argument to `None` and initialize the list inside the function: `def my_func(arg=None): if arg is None: arg = []` -
M511 - mutable default arg of type Dict
cause A dictionary (a mutable data type) was used as a default argument in a function definition, causing all function calls to share the same dictionary object.fixChange the default argument to `None` and initialize the dictionary inside the function: `def my_func(config=None): if config is None: config = {}`
Warnings
- gotcha Python's default arguments are evaluated only once, when the function is defined. If a mutable object (like a list, dictionary, or set) is used as a default argument, all subsequent calls to that function will share the *same instance* of that mutable object. Modifications to it will persist across calls, leading to unexpected behavior.
- gotcha flake8-mutable specifically checks for mutable default arguments (M511). Other similar issues, such as mutable class attributes shared across instances, are not covered by this specific plugin but might be caught by other linters like `flake8-bugbear` (B006) or `ruff` (RUF012).
Install
-
pip install flake8-mutable
Quickstart
import os
def my_function_with_footgun(a, b=[]):
# M511: mutable default arg of type List
b.append(a)
return b
def my_safe_function(a, b=None):
if b is None:
b = []
b.append(a)
return b
# To run flake8-mutable, you'd typically execute via the flake8 CLI.
# Example: flake8 your_script.py
# This code demonstrates the issue and the fix.
# Running `flake8` on a file containing `my_function_with_footgun`
# will produce an M511 error.