Python 枚举详解:创建、属性访问、继承与高级用法
本文深入解析 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 枚举的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









