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

如何修改枚举属性,实现dataclass内容的直接访问?

问题:简化枚举类中Dataclass属性的访问方式

你定义了如下Dataclass和枚举类:

from dataclasses import dataclass
from abc import ABC
from typing import Union, ClassVar
from enum import Enum

@dataclass
class BaseObject(ABC):
    obj: int
    data: Union[str, int, float, None] = None
    datatype: ClassVar[type]
    datalen: ClassVar[int]
    readonly: bool = True

@dataclass
class StrObject(BaseObject):
    datatype = str
    datalen = 16

# 生成唯一ID的示例函数
def next_id():
    global _id_counter
    _id_counter += 1
    return _id_counter

_id_counter = 0

class ObjectsPSI9000(Enum):
    DEVICE_TYPE = StrObject(next_id())
    DEVICE_SN = StrObject(next_id())
    # 假设已定义FloatObject
    # NOMINAL_VOLT = FloatObject(next_id())
    # NOMINAL_CURR = FloatObject(next_id())

当前访问属性时需要写DEVICE_TYPE.value.obj,操作繁琐,希望能“解包”Dataclass内容,简化访问方式。


解决方案

方法一:自定义代理枚举基类

创建一个继承自Enum的基类,通过重写__getattr__方法,让枚举成员直接代理其value的属性:

class ProxyEnum(Enum):
    def __getattr__(self, name):
        try:
            # 优先访问枚举成员自身的属性
            return super().__getattr__(name)
        except AttributeError:
            # 自身没有该属性时,从value中获取
            return getattr(self.value, name)

修改你的枚举类继承这个基类:

class ObjectsPSI9000(ProxyEnum):
    DEVICE_TYPE = StrObject(next_id())
    DEVICE_SN = StrObject(next_id())

之后就可以直接通过枚举成员访问Dataclass的属性:

print(ObjectsPSI9000.DEVICE_TYPE.obj)
print(ObjectsPSI9000.DEVICE_TYPE.data)

方法二:让BaseObject实现描述符协议

让BaseObject实现__get__方法,使枚举成员直接等同于对应的Dataclass实例:

@dataclass
class BaseObject(ABC):
    obj: int
    data: Union[str, int, float, None] = None
    datatype: ClassVar[type]
    datalen: ClassVar[int]
    readonly: bool = True

    def __get__(self, instance, owner):
        return self

此时枚举成员本身就是BaseObject的实例,直接访问属性即可:

print(ObjectsPSI9000.DEVICE_TYPE.obj)

方法三:优化IDE自动补全(可选)

如果使用方法一,为了让IDE识别到Dataclass的属性并提供自动补全,可以重写__dir__方法,将value的属性加入枚举成员的属性列表:

class ProxyEnum(Enum):
    def __getattr__(self, name):
        try:
            return super().__getattr__(name)
        except AttributeError:
            return getattr(self.value, name)
    
    def __dir__(self):
        # 合并枚举自身属性和value的属性
        return super().__dir__() + dir(self.value)

内容的提问来源于stack exchange,提问作者Paweł Pietraszko

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 07:05:10