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

如何实现含可变成员、可按seq_id比较及哈希的Python Enum

实现满足特定需求的工业流程阶段枚举类

我正在编写一个类来表示工业流程的连续阶段,包含ADMISSION、PROCESSING、QC和DELIVERY这几个阶段。每个阶段拥有唯一的递增序列号seq_id、助记名称name,以及记录流经该阶段实例数量的字段n_instances:

@dataclass
class Stage:
    seq_id:       int
    name:         str
    n_instances:  int

由于这些阶段是固定的,执行期间不会变更,我决定将它们整合到一个Enum中。该Enum需要满足以下要求:
枚举成员需:

  1. 作为Stage的子类,无需访问value即可使用(类似IntEnum或StrEnum),具体要求:
    1. 可通过seq_id进行比较(例如Stages.DELIVERY > Stages.PROCESSING应为真)
    2. 可作为字典的键
    3. 使用name作为__str__的返回值
  2. 具备基于声明顺序生成的、从0到n的不可变连续seq_id
  3. 在成员声明时指定name,使用auto()时生成小写的成员名称

我已在实现中完成了第2和第3点,请问如何实现第1点及其子需求?


最终实现(感谢@EthanFurman的解答)

核心思路

  • 将Stage实例作为枚举成员,把seq_id直接存储在枚举成员的_value_中(seq_id仅在枚举内部有意义)
  • seq_id基于声明顺序自动生成(借助自动编号枚举模式),避免手动指定带来的无效值问题
  • 比较、哈希、字符串转换等方法在枚举类中实现,而非Stage类,因为这些行为与枚举成员的使用强绑定
  • 哈希基于枚举成员的_value_(不可变),避免因Stage实例的可变性导致哈希异常
from dataclasses import dataclass
from enum import Enum, auto
from functools import total_ordering
from typing import override

@dataclass
class Stage:
    label:        str
    n_instances:  int = 0

@total_ordering         
class Stages(Stage, Enum): # 满足需求1:成员为Stage的子类
    # 需求1.1:基于seq_id比较
    def __lt__(self, other):
        if self.__class__ is other.__class__:
            return self.value < other.value
        return NotImplemented
    
    def __eq__(self, other):
        if self.__class__ is other.__class__:
            return self.value == other.value
        return NotImplemented
    
    # 需求1.2:可作为字典键
    def __hash__(self):
        return hash(self.value)

    # 需求1.3:__str__返回name
    def __str__(self):
        return self.label

    # 需求2:自动生成连续seq_id
    def __new__(cls, label):
        # 自动编号生成seq_id
        value = len(cls.__members__) + 1

        obj = Stage.__new__(cls)
        # 将seq_id设为枚举成员的value
        obj._value_ = value
        return obj
    
    # 需求3:auto()生成小写成员名称
    @override
    def _generate_next_value_(name, start, count, last_values):
        return name.lower()

    ADMISSION = auto()
    PROCESSING = auto()
    QC = auto()
    DELIVERY = auto()

# 排序测试     
assert Stages.PROCESSING < Stages.DELIVERY

# 字典键测试
stage_to_color = {
    Stages.ADMISSION :  "#B10156",
    Stages.PROCESSING : "#F4B704",
    Stages.QC :         "#FD0002",
    Stages.DELIVERY :   "#7FB857"
}

assert stage_to_color[Stages.QC] == "#FD0002"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 16:54:54