Skip to main content

Python enum.Enum Best Practices and Core Use Cases for Beginners

· 5 min read
Serhii Hrekov
software engineer, creator, artist, programmer, projects founder

The enum.Enum class in Python's standard library provides a way to create sets of symbolic names (members) bound to unique, constant values. Using enums dramatically improves code readability, maintainability, and type safety compared to using raw strings or integers.

Key Best Practices

  1. Always Inherit from enum.Enum: Use enum.Enum for rich, non-integer values. Only use enum.IntEnum if you specifically need arithmetic operations or strict integer comparisons.
  2. Use Capitalized Names: Enum members are constants; follow the convention of using ALL_CAPS.
  3. Prioritize Member Identity: Always compare enum members using identity (is) or equality (==), not their raw values.

12 Distinct Use Cases and Examples

Here are practical examples demonstrating how to define, access, and use Enum effectively.

from enum import Enum, IntEnum, unique, auto
import json

# --- SETUP: Base Enums for Examples ---

# Case 1: Basic Status Codes (Readability over magic numbers)
class HttpStatus(Enum):
OK = 200
NOT_FOUND = 404
SERVER_ERROR = 500

# Case 2: Simple String Values (For API messaging)
class UserRole(Enum):
ADMIN = "administrator"
EDITOR = "content_editor"
VIEWER = "read_only"

# Case 3: Using auto() for Unique Values (Best for flags where value doesn't matter)
class Permission(Enum):
READ = auto()
WRITE = auto()
DELETE = auto()

# Case 6: Custom Attributes (Rich Enums)
class TaskPriority(Enum):
LOW = (0, "Can wait until next sprint.")
MEDIUM = (1, "Must be done this week.")
HIGH = (2, "Needs immediate attention.")

# Overriding __init__ to handle the tuple attributes
def __init__(self, level: int, description: str):
self.level = level
self.description = description

Access and Utility Examples

#Use Case / ExampleCode SampleAnnotation
4Iteration (Looping)for role in UserRole: print(role.name)Allows processing all possible members of the set.
5Accessing by Name/Valuestatus = HttpStatus['OK']role = UserRole('read_only')
7Comparison (Identity)if user_role is UserRole.ADMIN:Best Practice: Use identity (is) for the fastest, safest comparison.
8IntEnum for Math/DBclass LogLevel(IntEnum): INFO=10; WARN=20Allows arithmetic (LogLevel.INFO + 5), required when values are integers used numerically.
9Enforcing Uniqueness@unique \n class Color(Enum): \n RED = 1 \n GREEN = 2The @unique decorator raises an error if duplicate values are assigned.
10Attribute Access (Rich Enums)print(TaskPriority.HIGH.description)Accesses the custom data defined in the __init__ method (Case 6).
11Membership Checkif role in [UserRole.ADMIN, UserRole.EDITOR]:Safely checks if a member belongs to a specific subset.
12JSON/Serializationdata = {'role': UserRole.VIEWER.value}When serializing, always use the .value or .name property to prevent complex serialization errors.

Code Examples for Cases 10, 11, 12

# Case 10: Accessing Custom Attributes (from Case 6)
high_priority = TaskPriority.HIGH
print(f"Priority Level: {high_priority.level}")
print(f"Priority Description: {high_priority.description}")

# Case 11: Membership Check
def has_write_access(user_role: UserRole) -> bool:
if user_role in [UserRole.ADMIN, UserRole.EDITOR]:
return True
return False

print(f"Can EDITOR write? {has_write_access(UserRole.EDITOR)}")

# Case 12: Converting to JSON (Serialization)
response_data = {
"status": HttpStatus.OK.value,
"role_name": UserRole.VIEWER.name
}
# Only the simple types (int/str) are in the JSON object
json_output = json.dumps(response_data)
print(f"Serialized JSON: {json_output}")

# Case 7 Example: Comparing Members
current_status = HttpStatus.NOT_FOUND
if current_status is HttpStatus.NOT_FOUND:
print("The status is exactly NOT_FOUND.")

Sources and Further Reading

  1. Python Documentation - enum Library
  2. Python Documentation - IntEnum and unique
  3. Real Python - Python Enum: The Essential Guide