Detailed Introduction and Usage of Enum in Python

<span>Enum</span> (enumeration) is a standard library module introduced in Python 3.4 (<span>enum</span>) used to create enumeration types with named constants. Additionally, <span>Python</span> has added several extensions based on <span>enum</span>.

  • <span>IntEnum</span> is a special enumeration type provided by the <span>enum</span> module that inherits from <span>int</span>, allowing enumeration members to be directly compared with integers.
  • <span>StrEnum</span> is a new enumeration type added in Python 3.11, inheriting from <span>str</span>, making enumeration members also strings.
  • <span>Flag</span> or <span>IntFlag</span> is a special enumeration type provided by Python’s <span>enum</span> module that combines the features of <span>Enum</span> and bitwise operations, making it ideal for representing combinable flags.

Basic Operations

Creating enumeration types, obtaining enumeration names, values, and enumeration comparison operations

from enum import Enum

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


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

# Looping through
for color in Color:
    print(color)

# Enumeration comparison, converting Color(1) to Color type
if Color.RED == Color(1):
    print(Color.RED.value)

Automatic assignment and uniqueness guarantee

from enum import Enum, auto

# Automatically assign values using the auto method
class Color(Enum):
    RED = auto()
    GREEN = auto()
    BLUE = auto()


for color in Color:
    print(color.value)  # Output: 1 2 3

Using <span>@unique</span> decorator to ensure all values are unique

from enum import Enum, unique

@unique
class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3
    # YELLOW = 1  # This will raise ValueError

IntEnum Enumeration Type

Since it inherits from <span>int</span>, it can perform arithmetic operations and logical comparisons with integers

Creating IntEnum enumeration type

# Old version, same as below IntEnum
class Priority(int, Enum):
 pass
class Priority(IntEnum):
    pass

Creating, comparing, and performing operations on <span>value</span> numeric operations

from enum import IntEnum


class Priority(IntEnum):
    MEDIUM = 2
    LOW = 1
    HIGH = 3

# Logical operations
print(Priority.HIGH == 3)
# Enum comparison, cannot be directly compared with integers
print(Priority.HIGH == Priority(3))
# Arithmetic operations
print(Priority.MEDIUM + 1)

# Sorting
pris = sorted(Priority, key=lambda x: x.value, reverse=True)

print(pris)

StrEnum Enumeration Type

Similar to <span>IntEnum</span>, <span>StrEnum</span> inherits from <span>str</span>, a new enumeration type added in Python 3.11. Therefore, for versions less than 3.11, it is defined as follows:

class enum_name(str, Enum): 

It can also be operated like a string, such as comparing strings

from enum import StrEnum

class LogLevel(StrEnum):
    DEBUG = "debug"
    INFO = "info"
    WARNING = "warning"
    ERROR = "error"

print(LogLevel.INFO == "info")

Flag and IntFlag Enumeration Types

Enumerations used for bitwise operations:

from enum import Flag, auto

class Permissions(Flag):
    EXECUTE = auto()
    WRITE = auto()
    READ = auto()

# Combining permissions
rw = Permissions.READ | Permissions.WRITE
print(rw)  # Permissions.READ|WRITE

# Checking permissions
print(Permissions.READ in rw)  # True
print(Permissions.EXECUTE in rw)  # False

# Removing permissions
write_only = rw & ~Permissions.READ
print(write_only)  # Permissions.WRITE

<span>IntFlag</span> is similar to <span>IntEnum</span>, allowing integer comparisons and operations

class Permissions(IntFlag):
    EXECUTE = auto()
    WRITE = auto()
    READ = auto()
    ALL = EXECUTE | WRITE | READ
    RW = READ | WRITE

# Using predefined combinations
print(Permissions.RW)  # Permissions.READ|WRITE
    
print(rw == 6)  # True (4 + 2 = 6)
print(rw & 2 == 2)  # True

# Creating from an integer
combined = Permissions(5)  # READ (4) + EXECUTE (1)
print(combined)  # Permissions.READ|EXECUTE

Advanced Applications

Since classes defined based on <span>Enum</span> can also define member attributes, member methods, and class methods, as shown in the following example:

from enum import Enum, auto


class Priority(int,Enum):
    LOW = 1
    MEDIUM = 2
    HIGH = 3
    URGENT = auto()  # Automatically assigned to 4

    @property
    def is_high_priority(self):
        return self.value >= self.HIGH

    def is_low(self):
        return self < Priority.MEDIUM

    @classmethod
    def get_level(cls, level: int) -> list:
        return [status for status in cls if status <= level]


print(Priority.LOW.is_low())
print(Priority.URGENT.is_high_priority)
print(Priority.get_level(2))

Scenario Applications

When using <span>Enum</span> to define enumeration types, the data types are relatively singular, either <span>int</span> or <span>str</span>. We can define <span>value</span> as a tuple. For example, for HTTP request response statuses, we can put <span>code</span> and <span>message</span> into a tuple.

# status.py

from enum import Enum

from starlette import status


class HttpStatus(Enum):
    # Enumeration constants (must match constructor parameters)
    SUCCESS = (status.HTTP_200_OK, "Operation successful")
    ERROR = (status.HTTP_500_INTERNAL_SERVER_ERROR, "Server error")
    NOT_FOUND = (status.HTTP_404_NOT_FOUND, "Resource not found")

    @property
    def code(self) -> int:
        """Returns the status code"""
        return self.value[0]

    @property
    def message(self) -> str:
        """Returns the description"""
        return self.value[1]

    # Get enumeration instance by code (class method)
    @classmethod
    def get_by_code(cls, code: int) -> 'Status | None':
        for status in cls:
            if status.code == code:
                return status
        return None

    def __str__(self) -> str:
        return f"{self.name}(code={self.code}, message={self.message})"

if __name__ == "__main__":
    # Test class usage
    print(HttpStatus.SUCCESS)         
    print(HttpStatus.SUCCESS.code)   
    print(HttpStatus.SUCCESS.message) 

    # Find enumeration by code
    print(HttpStatus.get_by_code(404))
    print(HttpStatus.get_by_code(999))

    # Iterate through all enumeration values
    for status in HttpStatus:
        print(f"{status.name}: code={status.code}, message={status.message}")

Reconstructing <span>fastapi</span>‘s <span>JSONResponse</span>

# response.py

from starlette.responses import JSONResponse
from status import HttpStatus

class SuccessResponse(JSONResponse):
    def __init__(self, data=None, message=HttpStatus.SUCCESS.message, code=HttpStatus.SUCCESS.code, **kwargs):
        self.data = {
            "code": code,
            "message": message,
            "data": data
        }
        self.data.update(kwargs)
        super().__init__(content=self.data, status_code=code)

Creating a <span>web</span> service and starting it

from fastapi import FastAPI

import response

app = FastAPI()

@app.get("/")
def read_root():
    return response.SuccessResponse({"Hello": "World"})

if __name__ == "__main__":
    import uvicorn
    uvicorn.run('main:app', host='0.0.0.0', port=8080, reload=True)

View the effect:

Detailed Introduction and Usage of Enum in Python

Leave a Comment