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

Python如何实现可交叉引用的固定不可变命名条目集合?

解决方案

问题核心原因

Enum类定义阶段,所有成员的原始赋值还未被封装为枚举实例,同时Item类本身未完成初始化,无法直接引用已实例化的枚举成员,因此直接写ITEM_A或者Item.ITEM_A都会报错。

方案1:基于现有Enum最小改造(推荐,保留Enum所有特性)

核心思路:定义阶段用枚举成员的字符串名称标记依赖,在__init__阶段(此时所有枚举实例已经完成注册到类的__members__映射中)统一将字符串替换为真实的枚举实例,同时直接支持你需要的字典类型requirements。

import enum

class Item(enum.Enum):
    ITEM_A = {"size": 100, "requirements": {}}
    ITEM_B = {"size": 200, "requirements": {"ITEM_A": 1}}
    # 支持任意顺序的交叉引用,例如:
    # ITEM_C = {"size": 300, "requirements": {"ITEM_A": 2, "ITEM_B": 1}}

    def __new__(cls, *args, **kwds):
        value = len(cls.__members__) + 1
        obj = object.__new__(cls)
        obj._value_ = value
        return obj

    def __init__(self, values: dict):
        self.size = values["size"]
        # 批量替换依赖的字符串名称为真实枚举实例
        self.requirements = {}
        for item_name, count in values["requirements"].items():
            self.requirements[self.__class__[item_name]] = count

功能验证

# 枚举成员仍可正常作为字典键使用
available = {Item.ITEM_A: 22, Item.ITEM_B: 45}
print(available[Item.ITEM_A])  # 输出22

# 依赖扣减逻辑可正常执行
for r_item, r_count in Item.ITEM_B.requirements.items():
    available[r_item] -= r_count
print(available[Item.ITEM_A])  # 输出21,符合预期

方案2:普通类实现(不需要Enum特性的场景)

如果不需要Enum的遍历、按名/值查找等内置能力,可以用不可变普通类实现,手动预定义实例即可解决引用问题:

class Item:
    # 关闭动态属性修改,实现不可变
    __slots__ = ("_value", "size", "requirements")
    def __init__(self, value: int, size: int, requirements: dict):
        self._value = value
        self.size = size
        self.requirements = requirements

    # 实现哈希和相等判断,支持作为字典键
    def __hash__(self):
        return hash(self._value)
    def __eq__(self, other):
        return isinstance(other, Item) and self._value == other._value

# 按顺序初始化实例,后面的实例可直接引用前面已初始化的实例
ITEM_A = Item(1, 100, {})
ITEM_B = Item(2, 200, {ITEM_A: 1})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 22:54:07