You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何给Enum实例化的冻结数据类添加字符串字段会触发AttributeError?

冻结数据类结合Enum时添加字符串字段触发AttributeError的原因

问题背景

原本将冻结数据类Strand与Enum结合可正常实例化对象,但添加name: str字段后触发AttributeError: can't set attribute,添加tuple或int类型字段则无此问题。

原可运行代码

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)

修改后报错代码

@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

原因分析

核心原因是Enum元类会自动为枚举成员设置name属性,而冻结数据类恰好定义了同名的name字段,两者冲突触发报错:

  1. 创建Strands枚举类时,Enum元类会逐个处理成员,先调用Strand构造函数创建冻结数据类实例,此时name字段已被初始化并标记为只读(冻结数据类特性)。
  2. 随后Enum元类尝试给实例设置自己的name属性(对应枚举成员的标识名,比如"VIT"),但该属性已被冻结数据类设为只读,无法重赋值,因此抛出AttributeError。

之前的tuple或int字段无问题,是因为它们的字段名与Enum内部自动设置的属性(name、value等)不重名,不会触发冲突。

内容的提问来源于stack exchange,提问作者lapraswastaken

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 07:31:06