在多种编程语言中,例如C、C++和Java,枚举都是一种常用的数据类型。它们能够帮助开发者编写更安全、更具可读性的代码。
在Python早期版本中,枚举并非原生支持。然而,自3.4版本起,Python开始引入了枚举类型。本文将详细介绍如何在Python中创建枚举、如何使用它们,以及它们如何提升代码的可读性。
什么是枚举?它们的作用是什么?
枚举,或者说枚举类型,是一种通过它可以取值的集合来定义的数据类型。这个值集合被称为成员集。枚举使得你可以更精确地限定变量可以拥有的值,从而有助于编写类型安全的代码,并提高代码的可读性。
一些需要了解的术语
在讨论枚举时,我们首先需要明确一些术语,因为我们将在后续内容中频繁使用它们。这些术语包括“成员”和“值”。
- 成员:指的是构成枚举值集合的具名常量。例如,一个表示星期的枚举(Days)可能包含“星期日”、“星期一”、“星期二”等成员。
- 值:是在内部用来明确表示每个枚举成员的值。这使得进行比较成为可能。例如,在星期的枚举中,“星期日”的值可能为0,“星期一”的值为1,“星期二”的值为2,以此类推。
接下来,我们将探讨枚举是如何改善你的代码的。
枚举如何改进你的代码
枚举可以通过多种方式改进你的代码,使其更易于理解且不易出错。以下是一些你应该使用枚举的原因:
- 枚举可以清晰地定义变量或函数参数可以接受的取值范围。通过明确表达变量或函数参数的预期值,可以使代码更容易被他人理解。
- 枚举还可以使你的代码具有自我文档化的特性。这意味着你不需要额外添加注释或文档来指定函数期望的值,枚举本身就清晰地表达了这些信息。
- 同时,集成开发环境(IDE)能够在传递错误值时提示错误,并提供自动补全支持。
- 因此,你的代码会变得更具类型安全性,从而降低运行时错误的风险。
接下来,我们将讨论如何在Python中创建枚举。
如何在Python中创建枚举
Python自身并没有原生支持枚举类型,但在标准库中提供了`enum`模块。我们将在本教程中使用这个模块。在Python中,创建枚举有两种主要方法:使用类或者使用函数API。接下来我们将详细介绍这两种方法。
先决条件
为了学习本教程,你需要安装Python 3.4或更高版本。这个版本的Python在其标准库中包含了`enum`模块。如果你还没有安装,这里有一个教程可以帮助你:
此外,你需要具备一定的Python编程基础,包括基本的Python语法和一些面向对象编程的概念,例如类和继承。
#1. 类方法
创建枚举的第一种方式是使用类。首先,从`enum`模块导入`Enum`类。然后,通过创建一个继承自`Enum`类的类来定义枚举。
from enum import Enum class Direction(Enum): NORTH = 0 EAST = 1 SOUTH = 2 WEST = 3
你也可以为枚举的成员指定任何你想要的值。例如,我们可以不使用0、1、2和3来表示方向,而是使用它们对应的角度值:0、90、180和270。
from enum import Enum class Direction(Enum): NORTH = 0 EAST = 90 SOUTH = 180 WEST = 270
另外,使用`range`函数可以更简洁地生成上述代码。如下所示:
from enum import Enum class Direction(Enum): NORTH, EAST, SOUTH, WEST = range(0, 360, 90)
在这个例子中,我们使用`range`函数生成一组值。起始值为0,结束值为360(不包含),步长为90。然后,我们解构了这个可迭代对象,这类似于解构元组。如果你想了解更多关于元组解构的信息,可以查阅关于Python中元组的文章。
枚举类是抽象类,这意味着它们不应该被实例化。相反,可以直接访问它们的属性(即枚举的成员)。
#2. 函数方法
函数方法是子类方法的替代方案。
from enum import Enum Direction = Enum("Direction", ["NORTH", "EAST", "SOUTH", "WEST"])
在上面的代码片段中,我们创建了一个名为`Direction`的枚举,它有四个成员,这些成员作为第二个参数传递给`Enum`函数。默认情况下,这些成员的值从1开始分配,因此“NORTH”为1,“EAST”为2,以此类推。之所以从1开始而不是从0开始,是因为0在Python中被认为是false。为了使所有值都为true,这些值从1开始编号。
或者,你可以通过传递一个元组列表来为成员指定值。每个元组包含两个元素:成员的名称和该成员的值。
from enum import Enum Direction = Enum( name = "Direction", values = [ ("NORTH", "n"), ("EAST", "e"), ("SOUTH", "s"), ("WEST", "w"), ] )
你会注意到,在上面的例子中,我使用字符串而不是整数作为成员的值。这说明字符串和整数都可以作为值来使用。
如何使用枚举
在前一节中,我们介绍了如何创建枚举以及如何为成员赋值。本节将介绍如何使用枚举来访问和分配成员,以及如何进行相等性检查。
如何访问成员
有多种方法可以访问枚举的成员,包括点语法、括号和方括号语法。以下是一个演示的例子:
from enum import Enum # 创建一个枚举 class Day(Enum): SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY = range(1, 8) # 访问枚举成员 # 1. 使用点语法 print(Day.SUNDAY) # 2. 使用方括号 print(Day["MONDAY"]) # 3. 使用括号 print(Day(3))
在访问枚举成员后,你可以将其存储在变量中。请注意,访问成员会返回该成员对象的引用,而不是其值或名称。这一点在接下来的部分中非常重要。
访问名称和值
如前所述,当你访问枚举成员时,你会创建对该成员对象的引用。如果你需要访问枚举对象的名称或值,可以使用对象的`name`和`value`属性。
print(Day.SUNDAY.name, Day.SUNDAY.value)
检查是否相等
回顾一下,将枚举成员赋值给变量会创建一个对枚举成员对象的引用。因此,要检查变量是否具有特定的枚举成员,我们使用`is`运算符来检查枚举成员和变量是否指向同一个对象。
以下是一个示例:
today = Day.WEDNESDAY if today is Day.MONDAY: print("It's a Monday, :(") if today is Day.WEDNESDAY: print("Happy Wednesday")
或者,你可以使用`==`运算符。在`Enum`类的超类中,`==`运算符是对`is`运算符的封装。这是通过运算符重载来实现的。你可以在关于MagicMethods的文章中了解更多信息。无论如何,以下是使用`==`而不是`is`的例子。
today = Day.WEDNESDAY if today == Day.MONDAY: print("It's a Monday, :(") if today == Day.WEDNESDAY: print("Happy Wednesday")
再次强调,枚举比较是检查对象标识,而不是值。
最后的话
本文介绍了枚举的概念及其用途。我们还介绍了通过子类化`Enum`类以及使用函数式API来创建枚举的不同方法。
此外,我们还介绍了如何使用枚举、访问值以及进行比较。接下来,你可能想阅读我们关于TypeScript枚举的文章。