欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python 枚举类源码解析

程序员文章站 2022-04-04 14:40:31
1. EnumMeta 元类编程,生成类的类,可以动态生成类。 用法: type(name, bases, dict) name 类名: str bases 基类: tuple dict 属性: dict EnumMeta元类是用于生成Enum类,后续类都继承Enum类。 _get_mixins_方 ......

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