This rule raises an issue when a mutable object is used as the default value in dict.fromkeys() or contextvars.ContextVar().

Why is this an issue?

In Python, when you pass a mutable object as a default value to certain constructs, all instances share the same object reference rather than getting independent copies. This creates unintended shared state that leads to subtle mutation bugs.

Python evaluates the default value expression once when the code is defined, not each time it is used. The same object instance is then reused across all keys or contexts.

The problem with dict.fromkeys()

The dict.fromkeys(keys, value) method creates a dictionary with all specified keys pointing to the same value object. When this value is mutable (like a list or dictionary), all keys share the same object reference:

keys = ['a', 'b', 'c']
my_dict = dict.fromkeys(keys, [])
my_dict['a'].append(1)
print(my_dict)  # {'a': [1], 'b': [1], 'c': [1]}

The problem with ContextVar()

When you create a ContextVar with a mutable default value, that same object is shared across all contexts, which is particularly problematic in concurrent code.

What is the potential impact?

How to fix it

For dict.fromkeys(), replace it with a dictionary comprehension that creates a new instance for each key. For ContextVar(), use a factory pattern or omit the mutable default.

Code examples

Noncompliant code example

keys = ['a', 'b', 'c']
my_dict = dict.fromkeys(keys, [])  # Noncompliant

Compliant solution

keys = ['a', 'b', 'c']
my_dict = {key: [] for key in keys}

Noncompliant code example

from contextvars import ContextVar

my_var = ContextVar('my_var', default=[])  # Noncompliant

Compliant solution

from contextvars import ContextVar

my_var: ContextVar[list] = ContextVar('my_var')

Resources

Documentation

Related rules