Python 枚举详解:创建、属性访问、继承与高级用法

星野
星野
发布时间:2026-10-15 | 3人浏览过
原创

本文深入解析 Python 的 enum 模块,涵盖枚举类的创建、成员属性访问(name/value)、迭代遍历、唯一性校验(@unique)及自动赋值(auto)。详细讲解枚举的比较规则、方法重写、继承机制,以及 IntEnum 与 IntFlag 的区别,帮助开发者规范代码并提升可维护性。

Python 枚举基础概念

枚举(enum )是一组绑定到唯一常数值的符号名称,具备可迭代性和可比较性。使用 enum 创建具有良好定义的标识符,替代直接使用魔法字符串或整数,有助于提升代码的可读性与后期维护效率。

枚举的创建与属性访问

创建枚举

我们可以使用 class 语法创建一个枚举类型,方便进行读写操作。此外,根据函数 API 的描述定义,我们可以创建一个 enum 的子类,具体实现如下:


from enum import Enum

class HttpStatus(Enum):
  OK = 200
  BAD_REQUEST = 400
  FORBIDDEN = 403
  NOT_FOUND = 404
  REQUEST_TIMEOUT = 408
  SERVICE_UNAVAILABLE = 500

注意:枚举属性值可以是任意类型,如 int、str 等。如果具体值不重要,可以使用 auto 实例,系统会自动选择合适的值。若将 auto 与其他具体值混合使用,需格外小心。在枚举类型中,不允许设置相同的 name,但允许存在相同的 value。

enum 自带属性 name 和 value,这是日常工作中最常用的两个属性。我们可以通过打印语句查看具体结果:


print('Member: {}'.format(HttpStatus.OK))        # Member: HttpStatus.OK
print('Member name: {}'.format(HttpStatus.OK.name))   # Member name: OK
print('Member value: {}'.format(HttpStatus.OK.value))  # Member value: 200
print(repr(HttpStatus.OK))               # <enum 'HttpStatus'>
print(type(HttpStatus.OK))               # <HttpStatus.OK: 200>
print(isinstance(HttpStatus.OK, HttpStatus))      # True

枚举的迭代与遍历

枚举迭代

枚举支持迭代和遍历顺序。以下是一个简单的示例:


from enum import Enum, auto

# 创建
class HttpStatus(Enum):
  OK = 200
  BAD_REQUEST = 400
  FORBIDDEN = 403
  NOT_FOUND = 404
  REQUEST_TIMEOUT = 408
  SERVICE_UNAVAILABLE = 500
  OTHER = auto.value

# 迭代
for status in HttpStatus:
  print('{} : {}'.format(status.name, status.value))

打印结果如下:

OK : 200 BAD_REQUEST : 400 FORBIDDEN : 403 NOT_FOUND : 404 REQUEST_TIMEOUT : 408 SERVICE_UNAVAILABLE : 500 OTHER : <object object at 0x000002863E1D7B10>

可以看出,遍历输出的每一个 status 都是一个独立的枚举成员,分别拥有 name 和 value 属性。

另外,我们也可以使用如下代码形式来进行枚举遍历:


for name, member in HttpStatus.__members__.items():
  print('{} : {}'.format(name, member))

枚举成员与属性访问

通过枚举 value 进行访问,访问时需要使用元组()的形式,例如:


print(HttpStatus(200))   # HttpStatus.OK

通过枚举 name 进行访问,访问时需要使用列表[]的形式,例如:


print(HttpStatus['OK'])   # HttpStatus.OK

将属性赋予另一个 enum 成员,示例如下:


number = HttpStatus.OK
print(number)        # HttpStatus.OK

枚举值的唯一性校验

枚举值唯一

在上述创建的枚举类中,value 值是可以重复的。如果我们希望枚举类中的值保持唯一,可以使用装饰器 @unique,具体举例如下:


from enum import Enum, unique

# 创建
@unique
class HttpStatus(Enum):
  OK = 200
  BAD_REQUEST = 400
  FORBIDDEN = 403
  NOT_FOUND = 404
  REQUEST_TIMEOUT = 408
  SERVICE_UNAVAILABLE = 500
  OTHER = 200

运行上述代码后,会抛出如下异常:

ValueError: duplicate values found in <enum 'HttpStatus'>: OTHER -> OK

查看源代码可知,加入此装饰器的枚举类型,unique 方法会将其 __members__.items() 进行遍历,并追加到 duplicates 列表中。如果发现列表不为空,则抛出上述异常信息。

枚举的自动赋值与比较

枚举自动赋值

此功能适用于我们在使用枚举时,仅关注标识符含义而忽略具体值的情况。但如果需要与字符串或整数混合使用,需额外注意。以下是官方示例:


import unittest
from enum import auto, Enum

class TestEnum(unittest.TestCase):
  
  def test_auto_number(self):
    class Color(Enum):
      red = auto()
      blue = auto()
      green = auto()
  
    self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
    self.assertEqual(Color.red.value, 1)
    self.assertEqual(Color.blue.value, 2)
    self.assertEqual(Color.green.value, 3)
  
  def test_auto_name(self):
    class Color(Enum):
      def _generate_next_value_(self, start, count, last):
        return self
  
      red = auto()
      blue = auto()
      green = auto()
  
    self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
    self.assertEqual(Color.red.value, 'red')
    self.assertEqual(Color.blue.value, 'blue')
    self.assertEqual(Color.green.value, 'green')

可以发现,使用 auto() 得到的是整数自增型序列。如果需要其他赋值方式,只需在枚举类中重写 _generate_next_value_ 方法即可。

枚举比较

枚举对象之间可以进行比较,但不能直接与值进行比较。若需进行值比较,则枚举对象需继承 IntEnum 对象。举例如下:


import unittest
from enum import Enum, IntEnum

class TestEnum(unittest.TestCase):
  class Season(IntEnum):
    SPRING = 1
    SUMMER = 2
    AUTUMN = 3
    WINTER = 4

  def test_comparisons(self):
    season = self.Season

    self.assertEqual(season.SPRING, 1)

    class Part(Enum):
      SPRING = 1
      CLIP = 2
      BARREL = 3
      
    self.assertNotEqual(Part.SPRING, 1)
    self.assertNotEqual(Part.SPRING, season.SPRING)

TestEnum().test_comparisons()

在上述测试例子中,我们创建了两个继承类型不同的枚举类。可以看到,继承了 IntEnum 的 Season 可以进行值的比较;而继承了 Enum 的 Part 则不能进行值比较。此外,IntEnum 类型与 Enum 类型也不能进行比较,即使它们的属性和值完全相同。

枚举的方法定义与继承

枚举方法

枚举中可以定义枚举类自身特有的方法,也可以复写一些已在基类中定义好的方法,例如:__init__, __str__, __repr__ , __hash__ ,__format__ 等。具体示例如下:


from enum import Enum

class Mood(Enum):
  FUNKY = (1, "hello")
  HAPPY = (3, "world")

  def describe(self):
    return self.name, self.value

  def __init__(self, num, nice):
    self.num = num
    self.nice = nice

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

  @classmethod
  def favorite_mood(cls):
    return cls.HAPPY

  @property
  def testValue(self):
    return self.nice + ':' + str(self.num)

在上述定义的枚举类中,value 是一个枚举类型。我们可以定义 __init__ 方法去对应元组中的值,同时也复写了 __str__ 方法。

打印方法以查看效果:


print(Mood.favorite_mood())   # my custom str! (3, 'world')
print(Mood.HAPPY.describe())  # ('HAPPY', (3, 'world'))
print(str(Mood.FUNKY))     # my custom str! (1, 'hello')
print(Mood.FUNKY.testValue)   # hello:1

从输出结果看,我们自定义和复写的方法都已成功应用到 Mood 类中。

枚举继承

不同于 Java 中的枚举类,Python 中的枚举类是可以被继承的。但被继承的枚举类规定其不能定义任何成员,但可以定义抽象方法。具体示例如下:


class EnumExtend(unittest.TestCase):

  def test_extending(self):
    class Shade(Enum):
      def shade(self):
        print(self.name)

    class Color(Shade):
      red = 1
      green = 2
      blue = 3
    with self.assertRaises(TypeError):
      class MoreColor(Color):
        cyan = 4
        magenta = 5
        yellow = 6

  def test_extending2(self):
    class Shade(Enum):
      def shade(self):
        return self.name

    class Color(Shade):
      def hex(self):
        return '%s nice!' % self.value

    class MoreColor(Color):
      cyan = 4
      magenta = 5
      yellow = 6
    self.assertEqual(MoreColor.magenta.shade(), 'magenta')
    self.assertEqual(MoreColor.magenta.hex(), '5 nice!')

测试用例可以完美运行。我们可以发现:第一个方法中,抛出了 TypeError 的异常;第二个测试方法中,MoreColor 继承了 Color,Color 继承了 Shade,并且我们可以通过子类调用父类中的方法。

总结与扩展

总结

本节主要介绍了 enum 模块的基础知识,包含枚举的创建、枚举成员和属性的访问、枚举方法的创建、枚举的继承等。其中新版中的 _ignore_、_order_、_missing_ 等特性建议参考官网例子学习。另外,enum 的子类 IntEnum、IntFlag 等也是我们比较常用的枚举基类,本文中简单介绍了 IntEnum。IntFlag 相比 IntEnum 多了 &, |, ^, ~ 的操作,其他子类大家感兴趣也可以进一步了解。

代码地址

示例代码:Python-100-days-day036

以上就是一文读懂Python 枚举的详细内容,更多关于Python 枚举的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表