【python】Enum 枚举类

Enum 枚举类[1]

Enum 是一组与互不相同的值分别绑定的符号名,类似于全局变量。因为枚举通常表示常量,所以建议枚举成员命名时采用大写

定义

  1. 类定义

    class Color(Enum):  # class syntax
        RED = 1
        GREEN = 2
        BLUE = 3
    
  2. 方法定义

    Color = Enum('Color', ['RED', 'GREEN', 'BLUE'])  # functional syntax
    
    • 枚举的成员可以是一个用空格或逗号分隔的字符串(值默认auto):

      'RED GREEN BLUE' | 'RED,GREEN,BLUE' | 'RED, GREEN, BLUE'

    • 或是一个名称的迭代器对象: ['RED', 'GREEN', 'BLUE']

    • 或是一个 (名称, 值) 对的迭代器对象: [('CYAN', 4), ('MAGENTA', 5), ('YELLOW', 6)]

    • 或是一个映射对象: {'CHARTREUSE': 7, 'SEA_GREEN': 11, 'ROSEMARY': 42}

基本概念

Color = Enum("Color", ["RED", "GREEN"])

assert Color.RED.name == "RED"  # 成员的名称
assert Color.GREEN.value == 2  # 成员的值
  • Color 是一个 枚举 (或 enum
  • 属性 Color.REDColor.GREEN 等是枚举成员,并且在功能上是常量。
  • 枚举成员有 namesvalues 等属性(Color.RED 的名称是 REDColor.GREEN 的值是 2)

🗒️ 备注:有些地方会检查是否是真正的 str 而不是 str 的子类 (例如使用 type(unknown) == str 而不是 isinstance(unknown, str)),在这些地方你将需要使用 str(StrEnum.member)

基本使用方式

Color = Enum("Color", ["RED", "GREEN"])

assert Color(1) == Color.RED  # 通过值查找现有成员
assert Color["GREEN"] == Color.GREEN # 通过名称查找现有成员
assert Color.RED in Color  # __contains__
assert list(Color) == [i for i in Color]  # __iter__,[<Color.RED: 1>, <Color.GREEN: 2>]
assert len(Color) == 2  # __len__,返回 cls 中成员的数量
list(reversed(Color))  # __reversed__,按定义的逆序返回 cls 中的每个成员

特殊使用方式

auto()

enum.auto 实例被替换为枚举成员的适当值。

  • StrEnum 默认为成员名称的小写版本,
  • 而其他枚举默认为 1 并由此递增。

_missing_(cls, value) 缺省值处理

一个用来查找不存在于 cls 中的值的类方法。 在默认情况下它将不做任何事,但可以被重写以实现自定义的搜索行为:

from enum import StrEnum, auto

class Build(StrEnum):
    DEBUG = auto()
    OPTIMIZED = auto()
    UNKNOWN = auto()

    @classmethod
    def _missing_(cls, value):
        value = value.lower()
        for member in cls:
            if member.value == value:
                return member
        return cls.UNKNOWN

print(Build.DEBUG)  # debug
print(Build('deBUG'))  # debug
print(Build('dev'))  # unknown

__init__ vs __new__

如果定义了 __new__()__init__(),则枚举成员的值将被传给这些方法。当你想要定制 Enum 成员的实际值时必须使用 __new__()。 任何其他修改可以用 __new__() 也可以用 __init__(),应优先使用 __init__()

class Planet(Enum):
    MERCURY = (3.303e+23, 2.4397e6)
    VENUS   = (4.869e+24, 6.0518e6)
    EARTH   = (5.976e+24, 6.37814e6)
    MARS    = (6.421e+23, 3.3972e6)
    JUPITER = (1.9e+27,   7.1492e7)
    SATURN  = (5.688e+26, 6.0268e7)
    URANUS  = (8.686e+25, 2.5559e7)
    NEPTUNE = (1.024e+26, 2.4746e7)

    def __init__(self, mass, radius):
        self.mass = mass       # in kilograms
        self.radius = radius   # in meters

    @property
    def surface_gravity(self):
        G = 6.67300E-11  # universal gravitational constant  (m3 kg-1 s-2)
        return G * self.mass / (self.radius * self.radius)

Planet.EARTH.value  # (5.976e+24, 6378140.0)
Planet.EARTH.surface_gravity  # 9.802652743337129

举例来说,如果你要向构造器传入多个条目,但只希望将其中一个作为值:

class Coordinate(bytes, Enum):
    """
    Coordinate with binary codes that can be indexed by the int code.
    """
    def __new__(cls, value, label, unit):
        obj = bytes.__new__(cls, [value])
        obj._value_ = value
        obj.label = label
        obj.unit = unit
        return obj

    PX = (0, 'P.X', 'km')
    PY = (1, 'P.Y', 'km')
    VX = (2, 'V.X', 'km/s')
    VY = (3, 'V.Y', 'km/s')

print(Coordinate['PY'])  # Coordinate.PY
print(Coordinate(3))  # Coordinate.VY

⚠️警告:不要调用 super().__new__(),因为只能找到仅用于查找的 __new__;请改为直接使用该数据类型。

普通方法和特殊方法

枚举是 Python 的类,可带有普通方法和特殊方法。假设有如下枚举:

class Mood(Enum):
    FUNKY = 1
    HAPPY = 3

    def describe(self):
        # self is the member here
        return self.name, self.value

    def __str__(self):
        return 'my custom str! {0}'.format(self.value)

    @classmethod
    def favorite_mood(cls):
        # cls here is the enumeration
        return cls.HAPPY

旗标 Flag

为了符合规范,旗标的值必须为二的乘方,且名称不可重复。 因此,除了别名的定义 Enum 之外,没有值 (即 0) 或是几个二的乘方值之和 (如 3) 的旗标也会被视为别名。

class Perm(Flag):
    R = 4
    W = 2
    X = 1
    A = R|W|X

assert (Perm.R | Perm.W).name == "R|W"  # effectively Perm(0)
assert (Perm.R & Perm.W).name is None  # effectively Perm(0)
assert bool(Perm.R & Perm(6)) is True

  1. Python 版本:3.11 ↩︎

posted @ 2024-07-16 23:51  hd092336  阅读(1)  评论(0编辑  收藏  举报