This rule raises an issue when a mutable object is used as the default value in dict.fromkeys() or contextvars.ContextVar().
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.
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]}
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.
ContextVar, shared mutable defaults can cause race conditionsFor 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.
keys = ['a', 'b', 'c'] my_dict = dict.fromkeys(keys, []) # Noncompliant
keys = ['a', 'b', 'c']
my_dict = {key: [] for key in keys}
from contextvars import ContextVar
my_var = ContextVar('my_var', default=[]) # Noncompliant
from contextvars import ContextVar
my_var: ContextVar[list] = ContextVar('my_var')
dict.fromkeys() methodcontextvars.ContextVar