Почему я получаю AttributeError при добавлении строкового поля в класс данных, созданный Enum?

Меня смущает такое поведение: у меня есть замороженный класс данных, из которых когда-либо нужны только 10, поэтому я хотел поместить их в Enum и сделал это успешно. Позже я понял, что хочу дать им имя, и вдруг Enum не может создать экземпляр класса данных.

import enum
import dataclasses as dc

class Stats(int, enum.Enum):
    HP = 0
    STA = 1
    SPD = 2
    ATK = 3
    DEF = 4
    SPATK = 5
    SPDEF = 6

@dc.dataclass(frozen=True)
class Strand:
    keeps: tuple[Stats, ...]
    costs: int

class Strands(Strand, enum.Enum):
    VIT =   ((Stats.HP,),              1000)
    END =   ((Stats.STA,),             1000)
    LTH =   ((Stats.SPD,),             1000)
    AGG =   ((Stats.ATK,),             1000)
    HRD =   ((Stats.DEF,),             1000)
    GFT =   ((Stats.SPATK,),           1000)
    DOM =   ((Stats.SPDEF,),           1000)
    VIGOR = ((Stats.HP, Stats.STA),    5000)
    MIGHT = ((Stats.ATK, Stats.SPATK), 5000)
    IMMUN = ((Stats.DEF, Stats.SPDEF), 5000)

Вышеупомянутое, что у меня было до добавления строкового поля, работает успешно - оно ничего не делает. Я добавляю строку в Strand и изменяю Enum следующим образом:

@dc.dataclass(frozen=True)
class Strand:
    keeps: tuple[Stats, ...]
    costs: int
    name: str

class Strands(Strand, enum.Enum):
    VIT =   ((Stats.HP,),              1000, "Vitality")
    END =   ((Stats.STA,),             1000, "Endurance")
    LTH =   ((Stats.SPD,),             1000, "Lithe")
    AGG =   ((Stats.ATK,),             1000, "Aggressive")
    HRD =   ((Stats.DEF,),             1000, "Hardening")
    GFT =   ((Stats.SPATK,),           1000, "Gifted")
    DOM =   ((Stats.SPDEF,),           1000, "Dominant")
    VIGOR = ((Stats.HP, Stats.STA),    5000, "Vigor")
    MIGHT = ((Stats.ATK, Stats.SPATK), 5000, "Mighty")
    IMMUN = ((Stats.DEF, Stats.SPDEF), 5000, "Immunity")

Когда я запускаю его с этими изменениями, он больше не завершается успешно и вместо этого выдает следующую ошибку:

Traceback (most recent call last):
  File "test.py", line 20, in <module>
    class Strands(Strand, enum.Enum):
  File "C:\Program Files\Python310\lib\enum.py", line 298, in __new__
  File "<string>", line 5, in __init__
  File "C:\Program Files\Python310\lib\types.py", line 187, in __set__
    raise AttributeError("can't set attribute")
AttributeError: can't set attribute

Я не понимаю, почему это происходит, и почему это происходит только со строками, а не с tuple или int. Насколько я могу судить, python str являются неизменяемыми, как и два других типа в Strand, хотя я не уверен, почему это имеет значение, поскольку вы можете иметь изменяемые типы в замороженном классе данных.

Есть ли что-то странное, что происходит при инициализации замороженного класса данных строкой, когда инициализация выполняется Enum?

На самом деле я не ищу решения, так как проблему довольно легко обойти, я просто сбит с толку таким поведением и задаюсь вопросом, есть ли объяснение. Я использую Python 3.10.2 — я не проверял это с другими версиями Python.

Интересно, что это не проблема с замороженным классом данных, так как с frozen=False проблема сохраняется.

Yevhen Kuzmovych 11.11.2022 13:33

@YevhenKuzmovych Отмечено - тогда я обновлю заголовок. Спасибо!

lapraswastaken 11.11.2022 13:50
14 Задание: Типы данных и структуры данных Python для DevOps
14 Задание: Типы данных и структуры данных Python для DevOps
проверить тип данных используемой переменной, мы можем просто написать: your_variable=100
Python PyPDF2 - запись метаданных PDF
Python PyPDF2 - запись метаданных PDF
Python скрипт, который будет записывать метаданные в PDF файл, для этого мы будем использовать PDF ридер из библиотеки PyPDF2 . PyPDF2 - это...
Переменные, типы данных и операторы в Python
Переменные, типы данных и операторы в Python
В Python переменные используются как место для хранения значений. Пример переменной формы:
Почему Python - идеальный выбор для проекта AI и ML
Почему Python - идеальный выбор для проекта AI и ML
Блог, которым поделился Harikrishna Kundariya в нашем сообществе Developer Nation Community.
Как автоматически добавлять котировки в заголовки запросов с помощью PyCharm
Как автоматически добавлять котировки в заголовки запросов с помощью PyCharm
Как автоматически добавлять котировки в заголовки запросов с помощью PyCharm
Анализ продукта магазина на Tokopedia
Анализ продукта магазина на Tokopedia
Tokopedia - это место, где продавцы могут продавать свои товары. Товар должен быть размещен на витрине, чтобы покупателям было легче найти товар...
2
2
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Через какое-то время я понял это. Судя по всему, Enum имеет встроенное ненастраиваемое поле с именем name, которое конфликтует с вашим полем с таким же именем name. Если вы измените имя name на другое, это будет работать, как и ожидалось.

value — другое неустанавливаемое поле.
Ethan Furman 11.11.2022 20:21

Другие вопросы по теме