Advanced Enumerations HOWTO¶
While basic enums map a name to a scalar value, Python's enum module supports multi-attribute members, complex behavior calculations, and dynamic enumeration generation.
Multi-Value Enums with Custom __init__¶
Enum members can represent rich entities with multiple properties by defining a custom __init__() method:
from enum import Enum
class Planet(Enum):
# Members defined with tuples: (mass_kg, radius_meters)
MERCURY = (3.303e+23, 2.4397e+6)
VENUS = (4.869e+24, 6.0518e+6)
EARTH = (5.976e+24, 6.37814e+6)
MARS = (6.421e+23, 3.3972e+6)
def __init__(self, mass: float, radius: float):
self.mass = mass
self.radius = radius
@property
def surface_gravity(self) -> float:
# Universal gravitational constant G = 6.67300E-11
G = 6.67300e-11
return G * self.mass / (self.radius ** 2)
def surface_weight(self, other_mass: float) -> float:
return other_mass * self.surface_gravity
# Calculate weight of a 75kg astronaut on Mars
astronaut_mass = 75.0
mars_weight = Planet.MARS.surface_weight(astronaut_mass)
earth_weight = Planet.EARTH.surface_weight(astronaut_mass)
print(f"Weight on Earth: {earth_weight:.1f} N")
print(f"Weight on Mars: {mars_weight:.1f} N")
Weight on Earth: 735.1 N Weight on Mars: 278.4 N
Functional API for Dynamic Enums¶
When member names are determined at runtime (e.g. read from an external database or config file), construct enums dynamically:
from enum import Enum
# Passing space-separated names (auto-assigned integers starting from 1)
Role = Enum("Role", "ADMIN EDITOR VIEWER GUEST")
print(Role.ADMIN) # Role.ADMIN
print(Role.ADMIN.value) # 1
# Or passing dictionary with explicit values:
Status = Enum("Status", {"ACTIVE": "act", "INACTIVE": "inact"})
JSON Serialization for Enums¶
Standard json.dumps() raises TypeError when attempting to serialize an Enum member. Use this clean encoder recipe:
import json
from enum import Enum
class Color(Enum):
RED = "#ff0000"
GREEN = "#00ff00"
BLUE = "#0000ff"
class EnumEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Enum):
return obj.value
return super().default(obj)
data = {"theme": "dark", "accent_color": Color.GREEN}
json_output = json.dumps(data, cls=EnumEncoder)
print(json_output)
# {"theme": "dark", "accent_color": "#00ff00"}