Python3.11的StrEnum的MRO在__str__和__repr__方面有何不同之处?

4
Python3.11引入了StrEnumIntEnum,它们分别继承自strint,并且还继承了ReprEnum,后者又继承了Enum
实际上,ReprEnum的实现是空的。
>>> print(inspect.getsource(ReprEnum))
class ReprEnum(Enum):
    """
    Only changes the repr(), leaving str() and format() to the mixed-in type.
    """

如果我创建一个StrEnum并检查MRO,我可以看到str排在第一位。
class Strings(StrEnum):
    A = "a"

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

无论是str还是Enum都定义了__str____repr__
>>> str.__repr__
<slot wrapper '__repr__' of 'str' objects>
>>> str.__str__
<slot wrapper '__str__' of 'str' objects>
>>> Enum.__repr__
<function Enum.__repr__ at 0x7ffff69f72e0>
>>> Enum.__str__
<function Enum.__str__ at 0x7ffff69f7380>

那么,__repr__ 是如何从 Enum 继承而来的,而 __str__ 又是如何从 str 继承而来的呢?
1个回答

3
__repr__方法是从Enum(通过StrEnum)继承而来的常规方式。
>>> Strings.__repr__ is StrEnum.__repr__ is Enum.__repr__
True

对于__str__方法,元类EnumType检查是否存在ReprEnum并将混入数据类型的strformat处理提升到类命名空间中,在类定义时这里
class EnumType(type):

    ...

    def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **kwds):

        ...

        # Also, special handling for ReprEnum
        if ReprEnum is not None and ReprEnum in bases:
            if member_type is object:
                raise TypeError(
                        'ReprEnum subclasses must be mixed with a data type (i.e.'
                        ' int, str, float, etc.)'
                        )
            if '__format__' not in classdict:
                enum_class.__format__ = member_type.__format__
                classdict['__format__'] = enum_class.__format__
            if '__str__' not in classdict:
                method = member_type.__str__
                if method is object.__str__:
                    # if member_type does not define __str__, object.__str__ will use
                    # its __repr__ instead, so we'll also use its __repr__
                    method = member_type.__repr__
                enum_class.__str__ = method
                classdict['__str__'] = enum_class.__str__

        ...

现在,由于类命名空间中直接可以找到Strings.__str__方法,无需遍历MRO(方法解析顺序)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接