Python 枚举类源码解析

发布时间:2019-05-02 07:04:02编辑:auto阅读(1866)

    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
    

关键字