Python LinuxWindowsmacOS

Python: dataclass mutable default вызывает ошибку при запуске

  • Обновлено
  • Чтение ≈ 3 минуты

Краткий ответ

dataclass сообщает о недопустимом изменяемом значении по умолчанию: замените список, словарь или множество на field(default_factory=...), чтобы каждый объект получал собственное значение.

В этой статье
  1. Что происходит и как распознать неисправность
  2. Как отличить причины
  3. Пошаговая диагностика и исправление
  4. Команды и примеры для проверки
  5. Как проверить результат и что делать дальше

#Что происходит и как распознать неисправность

При объявлении класса с @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 без параметров для получения независимого экземпляра.

#Пошаговая диагностика и исправление

  1. Найдите поле из tracebackОткройте полный текст ошибки в терминале и выделите имя поля после for field. В редакторе перейдите к соответствующему классу с декоратором @dataclass. Ошибка может возникать при импорте, до выполнения main(), поэтому не ищите её только в месте создания объекта.
  2. Сохраните копию файла и подтвердите тип поляСкопируйте изменяемый файл либо зафиксируйте текущие изменения в Git без секретов. Посмотрите правую часть аннотации, например items: list[str] = [] или options: dict = {}. Если значение уже создаётся через field(default_factory=...), ищите другой класс/поле из traceback.
  3. Добавьте правильный импорт fieldВ начале Python-файла, где уже импортирован dataclass, замените импорт на from dataclasses import dataclass, field. Не добавляйте импорт во внутрь класса. Сохраните файл и проверьте, что ваша среда использует поддерживаемую версию Python.
  4. Исправьте фабрику для изменяемого значенияЗамените items: list[str] = [] на items: list[str] = field(default_factory=list). Для словаря используйте field(default_factory=dict), для множества — set. Здесь фабрика передаётся без круглых скобок: default_factory=list, а не list(); иначе значение будет создано при объявлении класса.
  5. Для настраиваемого значения используйте callableЕсли новое поле должно начинаться с элементов, задайте field(default_factory=lambda: ["черновик"]); для вложенного объекта создайте через фабрику новый экземпляр, а не один общий объект уровня модуля. Проверьте, что фабрика не считывает изменяемое состояние между объектами без нужды.
  6. Проверьте независимость экземпляровСоздайте два экземпляра класса, добавьте элемент только первому и выведите содержимое обоих. У второго новый элемент появляться не должен. Если оба изменились, где-то осталась общая ссылка на объект, проверьте свойства и class variables.
  7. Убедитесь, что интерфейс создания не сломанЗапустите тесты проекта, проверьте сериализацию и вызовы конструктора ClassName(items=...). Если раньше конструктор требовал явный объект, теперь значением по умолчанию будет новый пустой контейнер. При несовместимости верните прежнюю версию из копии и согласуйте желаемые значения с авторами модели.

#Команды и примеры для проверки

Python
Пример для Python 3.9+ из-за аннотации list[str]; для старых выпусков используйте List[str] из typing.
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» отличается от ошибок типов при создании объекта.

Источники и обновления

Последнее обновление статьи: 2 ноября 2026. Версии программ и интерфейсы меняются — если шаги не совпадают с вашей версией, сверяйтесь с документацией производителя.