Modern Python Types
Enum Introduction
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
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
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 typeoutputColor.RED RED 1 <enum 'Color'>
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 typeoutputColor.GREEN GREEN 2 <enum 'Color'>
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 typeoutputColor.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}")
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()for status in Status:
pass 1 of 411# Values are automatically assigned 1, 2, 3, 412for statusStatus.PENDING in Status<enum 'Status'>:13 print(f"{status.namePENDING} = {status.value1}")outputPENDING = 1All 4 passes — pass 1 is the card above pass statusstatus.namestatus.value1 Status.PENDING PENDING 1 2 Status.APPROVED APPROVED 2 3 Status.REJECTED REJECTED 3 4 Status.CANCELLED CANCELLED 4
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")
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")def make_request(method: HttpMethod, url: str):
pass 1 of 212# Use in a function13def make_request(methodHttpMethod.GET: HttpMethod, url/api/users: str):14 print(f"{method.valueGET} {url/api/users}")outputGET /api/usersmake_request(HttpMethod.GET, "/api/users")
16make_request(HttpMethod.GETHttpMethod.GET, "/api/users")17make_request(HttpMethod.POSTHttpMethod.POST, "/api/users")def make_request(method: HttpMethod, url: str):
pass 2 of 212# Use in a function13def make_request(methodHttpMethod.POST: HttpMethod, url/api/users: str):14 print(f"{method.valuePOST} {url/api/users}")outputPOST /api/usersmake_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")
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.HIGHif task_priority == Priority.HIGH:
13# Equality comparison14if task_priorityPriority.HIGH == Priority.HIGHPriority.HIGH:15 print("High priority task!")outputHigh priority task!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 checkif 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}")
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:for day in Day:
pass 1 of 715print("All days:")16for dayDay.MONDAY in Day<enum 'Day'>:17 print(f" {day.nameMONDAY}: {day.value1}")output MONDAY: 1All 7 passes — pass 1 is the card above pass dayday.nameday.value1 Day.MONDAY MONDAY 1 2 Day.TUESDAY TUESDAY 2 3 Day.WEDNESDAY WEDNESDAY 3 4 Day.THURSDAY THURSDAY 4 5 Day.FRIDAY FRIDAY 5 6 Day.SATURDAY SATURDAY 6 7 Day.SUNDAY SUNDAY 7 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