Python 列舉類原始碼解析

晨濟發表於2019-01-08

1. EnumMeta

元類程式設計,生成類的類,可以動態生成類。
用法: type(name, bases, dict)
name -> 類名: str
bases -> 基類: tuple
dict -> 屬性: dict
EnumMeta元類是用於生成Enum類,後續類都繼承Enum類。

    class EnumMeta(type):
        def __new__(metacls, cls, bases, classdict):
            # member_type    列舉成員的型別
            # first_enum        第一個繼承的型別列舉類
            member_type, first_enum = metacls._get_mixins_(bases)    
            .......
_get_mixins_方法
    @staticmethod
    def _get_mixins_(bases):
        """
        返回用於建立列舉成員的型別,以及第一個繼承的型別列舉類。
        """
        # 這裡是Enum(metaclass=Enum)時用到的,bases=()
        if not bases:
            return object, Enum

        # 繼承自Enum類的子類,由以下方法判斷
        member_type = first_enum = None
        for base in bases:
            if  (base is not Enum and
                    issubclass(base, Enum) and
                    base._member_names_):
                raise TypeError("Cannot extend enumerations")
        # base is now the last base in bases
        if not issubclass(base, Enum):
            raise TypeError("new enumerations must be created as "
                    "`ClassName([mixin_type,] enum_type)`")

        # get correct mix-in type (either mix-in type of Enum subclass, or
        # first base if last base is Enum)
        if not issubclass(bases[0], Enum):
            member_type = bases[0]     # first data type
            first_enum = bases[-1]  # enum type
        else:
            for base in bases[0].__mro__:
                # most common: (IntEnum, int, Enum, object)
                # possible:    (<Enum `AutoIntEnum`>, <Enum `IntEnum`>,
                #               <class `int`>, <Enum `Enum`>,
                #               <class `object`>)
                if issubclass(base, Enum):
                    if first_enum is None:
                        first_enum = base
                else:
                    if member_type is None:
                        member_type = base

        return member_type, first_enum

相關文章