Magic numbers and strings scattered through code are hard to maintain and prone to typos. Enumerations provide named constants with type safety, enabling IDE autocomplete, preventing invalid values, and making code more self-documenting.

Why Use Enums?

  • Replace magic numbers/strings with semantic names
  • Ensure type safety (cannot use invalid values)
  • Auto-complete support in IDEs
  • Iterate over all valid values

Basic Enum

color
basic.py
Replay: real traced execution (multi-file project)
# Basic enum definition

from enum import Enum

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

# Access enum members
color = Color.RED
print(color)           # Color member
print(color.name)      # Member name
print(color.value)     # Member value
print(type(color))     # Enum type
# Basic enum definition

from enum import Enum

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

# Access enum members
color = Color.GREEN
print(color)           # Color member
print(color.name)      # Member name
print(color.value)     # Member value
print(type(color))     # Enum type
# Basic enum definition

from enum import Enum

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

# Access enum members
color = Color.BLUE
print(color)           # Color member
print(color.name)      # Member name
print(color.value)     # Member value
print(type(color))     # Enum type
  1. RED ← (empty), GREEN ← (empty), BLUE ← (empty), color ← Color.RED

    5class Color(Enum):6    RED→ (empty) = 17    GREEN→ (empty) = 28    BLUE→ (empty) = 3910# Access enum members11color→ Color.RED = Color.REDColor.RED12#@color=Color.GREEN, Color.BLUE13print(colorColor.RED)           # Color member14print(color.nameRED)      # Member name15print(color.value1)     # Member value16print(type(colorColor.RED))     # Enum type
    outputColor.RED
    RED
    1
    <enum 'Color'>
  1. RED ← (empty), GREEN ← (empty), BLUE ← (empty), color ← Color.GREEN

    5class Color(Enum):6    RED→ (empty) = 17    GREEN→ (empty) = 28    BLUE→ (empty) = 3910# Access enum members11color→ Color.GREEN = Color.GREENColor.GREEN12print(colorColor.GREEN)           # Color member13print(color.nameGREEN)      # Member name14print(color.value2)     # Member value15print(type(colorColor.GREEN))     # Enum type
    outputColor.GREEN
    GREEN
    2
    <enum 'Color'>
  1. RED ← (empty), GREEN ← (empty), BLUE ← (empty), color ← Color.BLUE

    5class Color(Enum):6    RED→ (empty) = 17    GREEN→ (empty) = 28    BLUE→ (empty) = 3910# Access enum members11color→ Color.BLUE = Color.BLUEColor.BLUE12print(colorColor.BLUE)           # Color member13print(color.nameBLUE)      # Member name14print(color.value3)     # Member value15print(type(colorColor.BLUE))     # Enum type
    outputColor.BLUE
    BLUE
    3
    <enum 'Color'>
Enum A class for creating enumerated constants with meaningful names and values, providing type safety and preventing the use of invalid values.

Auto Values

Use auto() to automatically generate sequential values.

auto_values.py
Replay: real traced execution (multi-file project)
# Auto-generating enum values

from enum import Enum, auto

class Status(Enum):
    PENDING = auto()
    APPROVED = auto()
    REJECTED = auto()
    CANCELLED = auto()

# Values are automatically assigned 1, 2, 3, 4
for status in Status:
    print(f"{status.name} = {status.value}")
  1. PENDING ← (empty), APPROVED ← (empty), REJECTED ← (empty), CANCELLED ← (empty)

    5class Status(Enum):6    PENDING→ (empty) = auto()7    APPROVED→ (empty) = auto()8    REJECTED→ (empty) = auto()9    CANCELLED→ (empty) = auto()
  2. for status in Status:

    pass 1 of 4
    11# Values are automatically assigned 1, 2, 3, 412for statusStatus.PENDING in Status<enum 'Status'>:13    print(f"{status.namePENDING} = {status.value1}")
    outputPENDING = 1
    All 4 passes — pass 1 is the card above
    passstatusstatus.namestatus.value
    1Status.PENDINGPENDING1
    2Status.APPROVEDAPPROVED2
    3Status.REJECTEDREJECTED3
    4Status.CANCELLEDCANCELLED4
auto() A function that automatically generates the next integer value in an Enum, reducing manual value assignment errors.

String Enums

Enums can have string values, useful for API methods or status codes.

string_enum.py
Replay: real traced execution (multi-file project)
# String enums for API methods

from enum import Enum

class HttpMethod(Enum):
    GET = 'GET'
    POST = 'POST'
    PUT = 'PUT'
    DELETE = 'DELETE'
    PATCH = 'PATCH'

# Use in a function
def make_request(method: HttpMethod, url: str):
    print(f"{method.value} {url}")

make_request(HttpMethod.GET, "/api/users")
make_request(HttpMethod.POST, "/api/users")
  1. GET ← (empty), POST ← (empty), PUT ← (empty), DELETE ← (empty)

    5class HttpMethod(Enum):6    GET→ (empty) = 'GET'7    POST→ (empty) = 'POST'8    PUT→ (empty) = 'PUT'9    DELETE→ (empty) = 'DELETE'10    PATCH→ (empty) = 'PATCH'1112# Use in a function13def make_request(method: HttpMethod, url: str):14    print(f"{method.value} {url}")1516make_request(HttpMethod.GETHttpMethod.GET, "/api/users")17make_request(HttpMethod.POST, "/api/users")
  2. def make_request(method: HttpMethod, url: str):

    pass 1 of 2
    12# Use in a function13def make_request(methodHttpMethod.GET: HttpMethod, url/api/users: str):14    print(f"{method.valueGET} {url/api/users}")
    outputGET /api/users
  3. make_request(HttpMethod.GET, "/api/users")

    16make_request(HttpMethod.GETHttpMethod.GET, "/api/users")17make_request(HttpMethod.POSTHttpMethod.POST, "/api/users")
  4. def make_request(method: HttpMethod, url: str):

    pass 2 of 2
    12# Use in a function13def make_request(methodHttpMethod.POST: HttpMethod, url/api/users: str):14    print(f"{method.valuePOST} {url/api/users}")
    outputPOST /api/users
  5. make_request(HttpMethod.POST, "/api/users")

    16make_request(HttpMethod.GET, "/api/users")17make_request(HttpMethod.POSTHttpMethod.POST, "/api/users")

Comparing Enums

Enums support equality and identity comparison. Identity check (is) is preferred for performance.

comparison.py
Replay: real traced execution (multi-file project)
# Comparing and checking enum values

from enum import Enum

class Priority(Enum):
    LOW = 1
    MEDIUM = 2
    HIGH = 3
    CRITICAL = 4

task_priority = Priority.HIGH

# Equality comparison
if task_priority == Priority.HIGH:
    print("High priority task!")

# Identity check (preferred, faster)
if task_priority is Priority.HIGH:
    print("Using identity check")

# Check membership
if Priority.CRITICAL in Priority:
    print("CRITICAL is a valid priority")
  1. LOW ← (empty), MEDIUM ← (empty), HIGH ← (empty), CRITICAL ← (empty)

    5class Priority(Enum):6    LOW→ (empty) = 17    MEDIUM→ (empty) = 28    HIGH→ (empty) = 39    CRITICAL→ (empty) = 41011task_priority→ Priority.HIGH = Priority.HIGHPriority.HIGH
  2. if task_priority == Priority.HIGH:

    13# Equality comparison14if task_priorityPriority.HIGH == Priority.HIGHPriority.HIGH:15    print("High priority task!")
    outputHigh priority task!
  3. if task_priority is Priority.HIGH:

    17# Identity check (preferred, faster)18if task_priorityPriority.HIGH is Priority.HIGHPriority.HIGH:19    print("Using identity check")
    outputUsing identity check
  4. if Priority.CRITICAL in Priority:

    21# Check membership22if Priority.CRITICALPriority.CRITICAL in Priority<enum 'Priority'>:23    print("CRITICAL is a valid priority")
    outputCRITICAL is a valid priority

Iterating Over Enums

Enums are iterable and support lookup by value or name.

iteration.py
Replay: real traced execution (multi-file project)
# Iterating over enums

from enum import Enum

class Day(Enum):
    MONDAY = 1
    TUESDAY = 2
    WEDNESDAY = 3
    THURSDAY = 4
    FRIDAY = 5
    SATURDAY = 6
    SUNDAY = 7

# Iterate over all days
print("All days:")
for day in Day:
    print(f"  {day.name}: {day.value}")

# Get enum by value
day = Day(3)
print(f"\nDay 3 is: {day.name}")

# Get enum by name
day = Day['FRIDAY']
print(f"Day named FRIDAY: {day.value}")
  1. MONDAY ← (empty), TUESDAY ← (empty), WEDNESDAY ← (empty), THURSDAY ← (empty)

    5class Day(Enum):6    MONDAY→ (empty) = 17    TUESDAY→ (empty) = 28    WEDNESDAY→ (empty) = 39    THURSDAY→ (empty) = 410    FRIDAY→ (empty) = 511    SATURDAY→ (empty) = 612    SUNDAY→ (empty) = 71314# Iterate over all days15print("All days:")16for day in Day:
    outputAll days:
  2. for day in Day:

    pass 1 of 7
    15print("All days:")16for dayDay.MONDAY in Day<enum 'Day'>:17    print(f"  {day.nameMONDAY}: {day.value1}")
    output  MONDAY: 1
    All 7 passes — pass 1 is the card above
    passdayday.nameday.value
    1Day.MONDAYMONDAY1
    2Day.TUESDAYTUESDAY2
    3Day.WEDNESDAYWEDNESDAY3
    4Day.THURSDAYTHURSDAY4
    5Day.FRIDAYFRIDAY5
    6Day.SATURDAYSATURDAY6
    7Day.SUNDAYSUNDAY7
  3. day ← Day.WEDNESDAY

    19# Get enum by value20day→ Day.WEDNESDAY = Day(3)21print(f"\nDay 3 is: {day.nameWEDNESDAY}")2223# Get enum by name24day→ Day.FRIDAY = Day['FRIDAY']Day.FRIDAY25print(f"Day named FRIDAY: {day.value5}")
    output
    Day 3 is: WEDNESDAY
    Day named FRIDAY: 5

@seealso dataclass_intro "Dataclasses" @seealso typing_intro "Type hints"

Exercise: practical.py

Create a game state machine using Enum with MENU, PLAYING, PAUSED, and GAME_OVER states