Меня смущает такое поведение: у меня есть замороженный класс данных, из которых когда-либо нужны только 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.
@YevhenKuzmovych Отмечено - тогда я обновлю заголовок. Спасибо!
Через какое-то время я понял это. Судя по всему, Enum
имеет встроенное ненастраиваемое поле с именем name
, которое конфликтует с вашим полем с таким же именем name
. Если вы измените имя name
на другое, это будет работать, как и ожидалось.
value
— другое неустанавливаемое поле.
Интересно, что это не проблема с замороженным классом данных, так как с
frozen=False
проблема сохраняется.