1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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