from enum import Enum


class Gender(Enum):
    male = 0
    female = 1


print(Gender(0))  # Gender.male
print(Gender(0).name)  # female
print(Gender(0).value)  # 0


class EnumWithLabel(Enum):
    """
    允许带 label 的枚举类型, 参考: https://docs.python.org/zh-cn/3/library/enum.html#when-to-use-new-vs-init
    """

    def __new__(cls, value, label):
        obj = object.__new__(cls)
        obj._value_ = value
        obj.label = label
        return obj


class GenderWithLabel(EnumWithLabel):
    male = (0, "MAN")
    female = (1, "WOMAN")


print(GenderWithLabel(0))  # GenderWithLabel.male
print(GenderWithLabel(0).value)  # 0
print(GenderWithLabel(0).label)  # MAN


class EnumWithDefault(Enum):
    """
    允许返回默认值的枚举类型, 不存在枚举值时不会报错
    如果需要修改默认值则需要覆盖 new_default_obj 函数
    """

    @classmethod
    def _missing_(cls, value):
        new_member = cls._create_pseudo_member_(value)
        return new_member

    @classmethod
    def new_default_obj(cls, value):
        obj = object.__new__(cls)
        obj._value_ = value
        obj._name_ = None
        return obj

    @classmethod
    def _create_pseudo_member_(cls, value):
        pseudo_member = cls._value2member_map_.get(value, None)
        if pseudo_member is None:
            pseudo_member = cls._value2member_map_.setdefault(value, cls.new_default_obj(value))
        return pseudo_member


class GenderWithDefault(EnumWithDefault):
    male = "0"
    female = "1"


print(GenderWithDefault("0"))  # GenderWithDefault.male
print(GenderWithDefault(0))  # GenderWithDefault.None
print(GenderWithDefault(0).name)  # None
print(GenderWithDefault(0).value)  # 0