#Что происходит и как распознать неисправность
При объявлении класса с @dataclass Python может выбросить ValueError: mutable default ... for field ... is not allowed: use default_factory. Это защита от случайно общего списка/словаря между экземплярами; начиная с Python 3.11 проверка опирается на нехешируемость значения.
#Как отличить причины
| Возможная причина | Как узнать | Что делать |
|---|---|---|
Общий список в полеПоле задано как items: list = []. | Ошибка возникает уже при импорте класса. | Примените field(default_factory=list). |
Словарь или множество в полеПоле содержит {} или set(). | Сообщение называет соответствующее поле. | Используйте dict/set как фабрику по умолчанию. |
| Нестандартный объект по умолчаниюПередан экземпляр другого изменяемого dataclass или нехешируемого объекта. | Простая замена на list не подходит по типу. | Создайте callable без параметров для получения независимого экземпляра. |
#Пошаговая диагностика и исправление
- Найдите поле из tracebackОткройте полный текст ошибки в терминале и выделите имя поля после
for field. В редакторе перейдите к соответствующему классу с декоратором@dataclass. Ошибка может возникать при импорте, до выполненияmain(), поэтому не ищите её только в месте создания объекта. - Сохраните копию файла и подтвердите тип поляСкопируйте изменяемый файл либо зафиксируйте текущие изменения в Git без секретов. Посмотрите правую часть аннотации, например
items: list[str] = []илиoptions: dict = {}. Если значение уже создаётся через field(default_factory=...), ищите другой класс/поле из traceback. - Добавьте правильный импорт fieldВ начале Python-файла, где уже импортирован
dataclass, замените импорт наfrom dataclasses import dataclass, field. Не добавляйте импорт во внутрь класса. Сохраните файл и проверьте, что ваша среда использует поддерживаемую версию Python. - Исправьте фабрику для изменяемого значенияЗамените
items: list[str] = []наitems: list[str] = field(default_factory=list). Для словаря используйтеfield(default_factory=dict), для множества —set. Здесь фабрика передаётся без круглых скобок:default_factory=list, а неlist(); иначе значение будет создано при объявлении класса. - Для настраиваемого значения используйте callableЕсли новое поле должно начинаться с элементов, задайте
field(default_factory=lambda: ["черновик"]); для вложенного объекта создайте через фабрику новый экземпляр, а не один общий объект уровня модуля. Проверьте, что фабрика не считывает изменяемое состояние между объектами без нужды. - Проверьте независимость экземпляровСоздайте два экземпляра класса, добавьте элемент только первому и выведите содержимое обоих. У второго новый элемент появляться не должен. Если оба изменились, где-то осталась общая ссылка на объект, проверьте свойства и class variables.
- Убедитесь, что интерфейс создания не сломанЗапустите тесты проекта, проверьте сериализацию и вызовы конструктора
ClassName(items=...). Если раньше конструктор требовал явный объект, теперь значением по умолчанию будет новый пустой контейнер. При несовместимости верните прежнюю версию из копии и согласуйте желаемые значения с авторами модели.
#Команды и примеры для проверки
from dataclasses import dataclass, field
@dataclass
class Task:
tags: list[str] = field(default_factory=list)
a = Task()
b = Task()
a.tags.append("срочно")
print(a.tags) # ["срочно"]
print(b.tags) # []#Как проверить результат и что делать дальше
Исправление подтверждено, когда модуль импортируется без ValueError, а изменения поля одного экземпляра не затрагивают другой. Ошибка про «mutable default» отличается от ошибок типов при создании объекта.