Page cover

enum 【列舉 Class】

簡介


What is Enum?

Python 中的 enum module 是 standard library 的一部分,並提供對建立 enumerations 的支援,枚舉是綁定到唯一常數值的一組符號名稱(成員)。

Enum 是 Enumeration 的縮寫,是 Python 中的一個 class,用於建立 enumerations;是一組綁定到唯一值的符號名稱。每個 enumeration member 都有一個 name 和一個 value。 enum module 定義了 5 個 enumeration classes,可用來建立唯一的 names 和 values sets:EnumIntEnumFlagIntFlag

Enumeration 的 members 可以透過這些符號名稱進行比較,使程式碼更具可讀性和可維護性。

How to Use Enum?

Enumerations 是 immutable (不可變的),即它們不能更改。 一旦它們被建立,它們就保持不變。 Enumeration 是一組值的符號名稱。 Enumerations 是 iterable,可以使用迴圈來遍歷它們。

要定義 enumeration,可以透過 2 種方式:

  1. 繼承 Enum Class。

  2. 將名稱 sequence 傳遞給 Enum() 函數。(函數式 API,語法類似 collections.namedtuple)

PYTHON
from enum import Enum

# Method 1
class Color(Enum):
    RED = 1    # Enum member: RED
    GREEN = 2  # Enum member: GREEN
    BLUE = 3   # Enum member: BLUE

print(Color.RED)        # Output: Color.RED
print(Color.RED.name)   # Output: RED
print(Color.RED.value)  # Output: 1

# Method 2
Animal = Enum('Animal', 'CAT DOG BIRD')

print(Animal.CAT)        # Output: Animal.CAT
print(Animal.CAT.name)   # Output: CAT
print(Animal.CAT.value)  # Output: 1

for i in Animal:
    print(i)
'''
Output: 
Animal.CAT
Animal.DOG
Animal.BIRD
'''

您可能使用 123, 來表示任務的狀態:"正在進行"、"已完成"和"未開始"。

現在,您可以在程式碼中,使用 TaskStatus.IN_PROGRESSTaskStatus.COMPLETEDTaskStatus.NOT_STARTED,它們比原始數字更容易理解。

from enum import Enum

class TaskStatus(Enum):
    IN_PROGRESS = 1
    COMPLETED = 2
    NOT_STARTED = 3

Enumerations 是 Class,但它們通常用於建立唯一的常數集合 (建立實例),並且通常沒有方法,儘管包含方法是完全有效的。

Why Use Enum?

Enums 用於理解的術語 (terms) 表達的特定概念,並且還提供一系列功能,使它們比簡單的常數和 String 更強大且更易於維護。

如果使用 String 容易出現錯別字,如果不查看文檔或實現,就無法立即清楚有效的 Strings 是什麼,並且 IDE 中沒有自動完成支持。

透過定義 enum Class,您可以清楚地了解可以應用了哪些類型,並且更難犯錯誤。 您可以獲得 IDE 中的自動完成等好處,您不會拼錯 string,並且將來可以輕鬆新增或更改 enum Class。

使用 enumerations 的主要好處包括:

  1. 提高代碼可讀性和可維護性:Enums 允許開發人員使用命名值,而不是容易混淆或不清楚的數字或 String,從而提高了可讀性。

  2. 安全或防止錯誤:使用 enums,可以減少因為傳遞無效參數而導致的錯誤。如果你定義了一個期望使用枚舉的函數或方法,那麼它只能接收在枚舉中定義的值。

  3. Enumeration Iteration:Enum members 可以使用循環進行 iterated。 這允許更動態地處理 enum 值並且可以簡化代碼。

  4. 豐富的 Comparisons:Enum members 可以透過這些符號運算子進行比較,還可以進行 sorted 和 hashed。

Python vs. C/C++ enumerations。

在 C/C++ 中,enumerations 是一種創建新類型的方法,它由一組命名的整數組成,enumeration 本身是整數類型。 在 Python 中,enumeration 的每個成員本身就是一個不同的值,而不僅僅是整數的別名。

When to Use Enum?

當您想要將一組相關的值組合在一起,並以一致的方式引用時,Enums 特別有用。例如:

  • State machine 中的狀態。

  • GUI 或 Web 應用程式的下拉式選單中的選項。

  • Categories, types or labels。 (例如: 產品類別)

  • Status codes or error codes。(例如: 錯誤和異常處理)

  • Handling Configuration Settings。

Conclusion

Python 中的 enum module 是創建 enumerable 常數的強大工具。透過使用 enums,開發人員可以編寫更易於閱讀、維護且不易出錯的程式碼。當處理一組代表某種狀態、類型或類別的預定義值時,它特別有用。

Enumeration data


Enumeration data: Enumeration 資料、enumerated 類型或 enum 是一種資料類型。 這是一個簡單的enumeration 範例:

PYTHON
from enum import Enum

class Color(Enum):
    RED = 1
    BLUE = 2
    GREEN = 3

print(Color.RED.name)   # Output: "RED"
print(Color.RED.value)  # Output: "1"

enumeration: Color enumeration members: RED, BLUE, GREEN 成員的名稱按照慣例為大寫,因為它們被視為常數。每個 enumeration member 都有兩個重要的屬性:namevaluename 屬性給出 member name (string),value 屬性給出成員的值。

Enum members, values


有兩個同名的 enum members 是無效的。但是,兩個 enum members 允許具有相同的值。 給定兩個具有相同值的 members AB(並且 A 首先定義),member BA 的別名。

PYTHON
import enum

class Shape(enum.Enum):
    DIAMOND = 1
    SQUARE = 2
    CIRCLE = 3
    ALIAS_FOR_SQUARE = 2

print(Shape.SQUARE)            # Output: Shape.SQUARE
print(Shape.ALIAS_FOR_SQUARE)  # Output: Shape.SQUARE
print(Shape(2))                # Output: Shape.SQUARE

class Shape(enum.Enum):
    SQUARE = 2
    SQUARE = 3

# Output: 
# TypeError: 'SQUARE' already defined as 2

範例 – 用法


  1. 如果需要根據使用者的輸入訪問 Enum member 或其值,可以使用 Enum.member 來獲取該 member,或使用 Enum(value) 透過其值來獲取 Enum member。

  2. Enumeration 值被 repr() 解析為 <enum 'EnumName'>.<member_name>,而不是它們的值。

  3. Enum members 是 hashable,這意味著它們可以在需要 hashable 物件的任何 context 中使用。 這包括作為 dictionaries 中的 keys 和 Sets 中的元素,它們也是 immutable。

PYTHON
from enum import Enum

class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3
    YELLOW = 4

# Accessing value of Enum member
print(Color.RED.value)  # Output: 1
print(Color.RED.name)   # Output: RED

# Accessing Enum member based on its value
print(Color(1))         # Output: Color.RED

# Accessing Enum member
print(Color.RED)        # Output: Color.RED
print(Color['RED'])     # Output: Color.RED

# =========================================================
print(repr(Color.RED))       # Output: <Color.RED: 1>
print(list(Color))           # Output: [<Color.RED: 1>, <Color.GREEN: 2>, <Color.BLUE: 3>]
print(list(reversed(Color))) # Output: [<Color.BLUE: 3>, <Color.GREEN: 2>, <Color.RED: 1>]
print(dir(Color))            # Output: ['BLUE', 'GREEN', 'RED', '__class__', '__doc__', '__members__', '__module__']
print(len(Color))            # Output: 3

print(type(Color))           # <class 'enum.EnumType'>
print(type(Color.RED))       # <enum 'Color'>
print(Color.RED in Color)    # Output: True
print(isinstance(Color.GREEN, Color)) # Output: True

# =========================================================
print(Color.RED is Color.BLUE)        # Output: False
print(Color.RED is not Color.BLUE)    # Output: True

print(Color.RED == Color.BLUE)        # Output: False
print(Color.RED != Color.BLUE)        # Output: True

# Enum members are not integers 
print(Color.RED == 1)                 # Output: False
#print(Color.RED < Color.BLUE)    
#print(Color.RED <= Color.BLUE) 

# =========================================================
# Iterating Enum
for i in Color:
    print(i)
'''
Color.RED
Color.GREEN
Color.BLUE
Color.YELLOW
'''

for name, member in Color.__members__.items():
    print(name, member)
'''
RED Color.RED
GREEN Color.GREEN
BLUE Color.BLUE
YELLOW Color.YELLOW
'''

# Used for detailed programmatic access
print([name for name, member in Color.__members__.items() if member.name != None])
# Output: ['RED', 'GREEN', 'BLUE', 'YELLOW']
'''
names = []
for name, member in Color.__members__.items():
    if member.name is not None:
        names.append(name)
'''

# =========================================================
# Enumeration members are hashable
# Use Enum members as dictionary keys
color_dict = {
    Color.RED: 'It symbolizes love and anger.',
    Color.GREEN: 'It symbolizes nature and tranquility.',
    Color.BLUE: 'It symbolizes sea and sky.',}
print(color_dict[Color.RED])     # Output: 'It symbolizes love and anger.'

# Use Enum members in sets
color_set = {Color.RED, Color.BLUE}
print(Color.GREEN in color_set)  # Output: False
print(Color.RED in color_set)    # Output: True

Enum


Enumenum enumerations 的 Base Class。

EnumType 負責在其他 enum Class 上設置正確的方法,包含: name, value, _generate_next_value_, __str__ 方法...。

IntEnum


IntEnumEnum 的用法大致相同,但它是 Enum 的 Subclass,且 enumeration 值是 int 的實例。

本質上,IntEnum members 可以參與所有 int 的 operations。如果對 IntEnum members 執行任何整數運算,則結果值將失去 enumeration 狀態。

PYTHON
from enum import IntEnum

class Number(IntEnum):
    ONE = 1
    TWO = 2
    THREE = 3

print(Number.THREE.value)       # Output: 1
print(Number.ONE + Number.TWO)  # Output: 3
print(Number.THREE + 5)         # Output: 8

# Loses its enumeration status
print(type(Number.THREE))     # Output: <enum 'Number'>
print(type(Number.THREE + 5)) # Output: <class 'int'>

StrEnum


StrEnumEnum 的用法大致相同,但它是 Enum 的 Subclass,且 enumeration 值是 str 的實例。

本質上,IntEnum members 可以參與所有 str 的 operations。如果對 StrEnum members 執行任何字串運算,則結果值將失去 enumeration 狀態。

PYTHON
from enum import StrEnum

class Number(StrEnum):
    ONE = "ONE"
    TWO = "TWO"
    THREE = "THREE"

print(Number.ONE.value) # Output: "ONE"

print(type(Number.TWO)) # Output: <enum 'Number'>
print(type(Number.TWO + "TWO"))        # Output: <class 'str'>
print(type(Number.TWO + Number.THREE)) # Output: <class 'str'>

EnumType


EnumTypeenum enumerations 的 Metaclass。 可以對 EnumType 進行Subclassing。

EnumType 負責在 enum 上設置正確的方法,包含: __call__, __repr____str____format__, __reduce__, __len__, __iter__ 方法...。

範例 – 衍生 Enumerations


透過擴展,不同類型的 IntEnum 也可以相互比較。但是,IntEnum 仍然無法與標準 Enum Enumerations 進行比較。

IntEnum 值的行為,也可以類似於整數。

PYTHON
from enum import IntEnum, Enum

class Shape(IntEnum):
    CIRCLE = 1
    SQUARE = 2

class Request(IntEnum):
    POST = 1
    GET = 2

print(Shape.CIRCLE == 1)             # Output: True
print(Shape.CIRCLE == Request.POST)  # Output: True

# =========================================================
class Color(Enum):
    RED = 1
    GREEN = 2
    
print(Shape.CIRCLE == Color.RED)     # Output: False

# =========================================================
# IntEnum To int
print(int(Shape.CIRCLE))                # Output: 1
# IntEnum To index
print(['a', 'b', 'c'][Shape.CIRCLE])    # Output: "b"
# IntEnum To len()
print([i for i in range(Shape.SQUARE)]) # Output: [0, 1]

Last updated

Was this helpful?