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

如何在Python中创建无元类冲突的FractionEnum?

实现FractionEnum的踩坑与解决过程

1. 初始尝试:元类冲突

尝试创建类似StrEnum/IntEnum的FractionEnum,直接继承fractions.Fraction和Enum:

class FractionEnum(fractions.Fraction, Enum):
    VALUE_1 = 1, 1
    VALUE_2 = 8, 9

运行后触发元类冲突错误:

TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

2. 解决元类冲突,但触发新错误

自定义元类解决冲突问题:

class FractionEnumMeta(type(Enum), type(fractions.Fraction)):
    pass

class FractionEnum(fractions.Fraction, Enum, metaclass=FractionEnumMeta):
    VALUE_1 = 1, 1
    VALUE_2 = 8, 9

元类冲突解决后,又出现新的类型错误:

File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/enum.py", line 289, in __new__
    enum_member = __new__(enum_class, *args)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/fractions.py", line 93, in __new__
    self = super(Fraction, cls).__new__(cls)

TypeError: Enum.__new__() missing 1 required positional argument: 'value'

问题根源在于Fraction的__new__方法调用父类构造时,错误触发了Enum的构造逻辑——Enum的__new__需要必填的value参数,两者构造流程不兼容(不像int/str可以直接与Enum混合实现)。

3. 替换__new__后,深拷贝触发枚举扩展错误

替换Fraction的__new__方法后,枚举可以正常工作,但深拷贝包含该枚举成员的对象时,再次报错:

/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/enum.py:497: in _create_
    _, first_enum = cls._get_mixins_(cls, bases)

具体错误内容:

# ensure final parent class is an Enum derivative, find any concrete
        # data type, and check that Enum has no members
        first_enum = bases[-1]
        if not issubclass(first_enum, Enum):
            raise TypeError("new enumerations should be created as "
                    "`EnumName([mixin_type, ...] [data_type,] enum_type)`")
        member_type = _find_data_type(bases) or object
        if first_enum._member_names_:
>           raise TypeError("Cannot extend enumerations")
E           TypeError: Cannot extend enumerations

复现代码:

class TestFractionEnum(FractionEnum):
    VALUE_1 = 1, 1
    VALUE_2 = 8, 9

class C:
    def __init__(self):
        self.fraction_enum = TestFractionEnum.VALUE_1

c = C()
print(c)
print(c.fraction_enum)
d = copy.copy(c)
print(d)
e = copy.deepcopy(c)
print(e)

4. 最终解决:重写__deepcopy__方法

给FractionEnum添加自定义的__deepcopy__方法,绕过深拷贝时的枚举构造逻辑,直接返回已存在的枚举成员,问题得以解决:

def __deepcopy__(self, memo):
    if type(self) == Fraction:
        return self
    for item in self.__class__:
        if self == item:
            return item
    assert f'Invalid enum: {self}'

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 15:47:40