Python Enums: The enum Module

· 3 min read · Updated March 13, 2026 · beginner
python stdlib enum constants best-practices

Enums (enumerations) are a way to define a set of named constant values. The Python enum module provides tools for creating enumerations, which are useful when you have a fixed set of related values that have semantic meaning in your code.

Why Use Enums?

Without enums, developers often use magic numbers or strings:

# Bad: magic numbers
status = 1  # What does 1 mean?

# Bad: magic strings  
status = "active"  # Typos won't be caught

Enums solve these problems by providing:

  • Type safety: IDEs can warn about invalid values
  • Readability: Code reads like English
  • Immutability: Values cannot be changed accidentally
  • Organization: Related constants are grouped together

Creating Your First Enum

from enum import Enum

class Status(Enum):
    PENDING = 1
    APPROVED = 2
    REJECTED = 3

# Accessing enum members
print(Status.PENDING)        # Status.PENDING
print(Status.PENDING.name)   # PENDING
print(Status.PENDING.value)  # 1

Comparing Enums

Enum members are compared by identity, not value:

from enum import Enum

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

print(Color.RED == Color.RED)      # True
print(Color.RED == 1)              # False (different types)
print(Color(2))                    # Color.GREEN (value to enum)
print(Color['GREEN'])              # Color.GREEN (name to enum)

Auto-Numbering Enums

Use auto to let Python assign values:

from enum import Enum, auto

class Direction(Enum):
    NORTH = auto()
    SOUTH = auto()
    EAST = auto()
    WEST = auto()

print([d.value for d in Direction])  # [1, 2, 3, 4]

Enum Methods

Enums provide useful methods:

from enum import Enum

class Status(Enum):
    PENDING = "pending"
    APPROVED = "approved"
    REJECTED = "rejected"

# Iterate over all members
for status in Status:
    print(f"{status.name}: {status.value}")

# Get enum from value
status = Status("approved")
print(status)  # Status.APPROVED

# Check if value exists
print("approved" in Status._value2member_map_)  # True

Flag Enums for Combinations

Use Flag when you need combinable bitwise values:

from enum import Flag, auto

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

# Combine permissions
admin = Permission.READ | Permission.WRITE | Permission.EXECUTE
print(admin)                    # Permission.READ|WRITE|EXECUTE
print(Permission.READ in admin) # True

IntEnum: Enums That Behave Like Integers

For cases where you need enum compatibility with integers:

from enum import IntEnum

class HTTPStatus(IntEnum):
    OK = 200
    NOT_FOUND = 404
    SERVER_ERROR = 500

# Works like an integer
print(HTTPStatus.OK == 200)     # True
print(HTTPStatus.OK + 1)        # 201

Enum with Methods

You can add methods to enum classes:

from enum import Enum

class Level(Enum):
    LOW = 1
    MEDIUM = 2
    HIGH = 3
    
    def describe(self):
        return f"{self.name} (value: {self.value})"
    
    @property
    def is_critical(self):
        return self == Level.HIGH

print(Level.HIGH.describe())     # HIGH (value: 3)
print(Level.HIGH.is_critical)   # True

Best Practices

  1. Use PascalCase for enum names: Status, Color, Direction
  2. Use UPPER_SNAKE_CASE for members: PENDING, ACTIVE, DONE
  3. Prefer enums over constants: Type safety is worth the extra typing
  4. Use auto() for simple sequences: Less maintenance when reordering

Common Gotchas

from enum import Enum

# Aliases - avoid this!
class BadEnum(Enum):
    A = 1
    B = 2
    C = 1  # This creates an alias!

print(BadEnum.C)        # BadEnum.A (not BadEnum.C!)
print(BadEnum.C is BadEnum.A)  # True

# Use enum.unique to catch this
from enum import unique, Enum

@unique
class GoodEnum(Enum):
    A = 1
    B = 2
    # C = 1  # Would raise ValueError

When to Use Enums

  • Status codes and states
  • Configuration options
  • Menu items or commands
  • Days of the week, months
  • Any fixed set of related values

See Also