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

Python 3.11中StrEnum的MRO对__str__与__repr__的继承机制差异问询

Python 3.11中StrEnum的MRO对__str__与__repr__的继承机制差异问询

这个问题问得特别到位,咱们一步步拆解来搞明白背后的逻辑:

首先先回顾下背景:Python 3.11新增了StrEnum和IntEnum,它们分别继承自str/int以及ReprEnum,而ReprEnum本身又是Enum的子类。有意思的是,ReprEnum的实现其实是空的,只有一段说明它作用的文档字符串:

import inspect
from enum import ReprEnum

print(inspect.getsource(ReprEnum))

输出结果是:

class ReprEnum(Enum):
"""
Only changes the repr(), leaving str() and format() to the mixed-in type.
"""

接下来看你定义的StrEnum子类的方法解析顺序(MRO):

from enum import StrEnum

class Strings(StrEnum):
    A = "a"

print(Strings.__mro__)

得到的MRO顺序是:

(<enum 'Strings'>, <enum 'StrEnum'>, <class 'str'>, <enum 'ReprEnum'>, <enum 'Enum'>, <class 'object'>)

你也注意到了,str和Enum都各自定义了__str__和__repr__方法:

# 查看str类的方法
print(str.__repr__)
# <slot wrapper '__repr__' of 'str' objects>
print(str.__str__)
# <slot wrapper '__str__' of 'str' objects>

# 查看Enum类的方法
from enum import Enum
print(Enum.__repr__)
# <function Enum.__repr__ at 0x7ffff69f72e0>
print(Enum.__str__)
# <function Enum.__str__ at 0x7ffff69f7380>

那为什么明明str在MRO里的位置比Enum靠前,__repr__却继承自Enum,而__str__继承自str呢?

其实核心就藏在ReprEnum的文档字符串里——它的设计意图就是只修改repr()的行为,把str()和format()的逻辑完全交给混合的原生类型(这里就是str)。而实现这个逻辑的关键,是枚举的元类EnumMeta在背后做了特殊处理:

  1. 对于__str__:按照ReprEnum的设计,直接沿用混合类型str的实现。因为MRO里str的位置确实更靠前,元类也没有干预这个方法的查找,所以调用str(Strings.A)时,会返回"a",和普通字符串的__str__效果一致。

  2. 对于__repr__:元类会根据ReprEnum的标记,调整方法查找的优先级,跳过str的__repr__,转而使用Enum的实现。这样调用repr(Strings.A)时,会返回<Strings.A: 'a'>,保留枚举成员的标识信息,符合枚举类型的调试需求。

简单来说,ReprEnum就是个标记类,它本身不需要写代码,只要告诉EnumMeta:这个混合类型枚举的repr()用枚举的逻辑,str()用原生类型的逻辑就行。

备注:内容来源于stack exchange,提问作者Abraham Murciano Benzadon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.21 15:58:04