Python Enum to String without Class Name
When using Python Enums, the default string output includes the class name (e.g., <MyEnum.MEMBER: 'value'>), which is often unsuitable for clean logging, API responses, or direct printing. This article demonstrates how to leverage Python's dunder methods (__str__, __repr__, __format__) to gain complete control over the string representation of your Enum members.
The Default Problem Statement​
By default, an Enum member prints its full, verbose representation, including the class name and the member name, which is usually not what's desired when serializing to a simple string.
from enum import Enum
class Color(Enum):
RED = 'red'
GREEN = 'green'
my_color = Color.RED
# Default print output:
# print(my_color) # Output: Color.RED
# print(str(my_color)) # Output: Color.RED
Solution 1: Controlling Standard String Output with __str__​
The __str__ method controls the output when an object is converted to a string using str() or when it is printed via the print() function. Overriding this method is the primary way to remove the class name from basic output.
class OutputMode(Enum):
COMPACT = 1
VERBOSE = 2
# Override __str__ to return only the member's value or name
def __str__(self):
# Recommended: return the raw value, which is useful for APIs
return str(self.value)
# Usage:
mode = OutputMode.COMPACT
print(f"Current mode value: {mode}") # Calls __str__ implicitly
print(str(mode))
# Output: 1
# Output: 1
class RoleNameOnly(Enum):
ADMIN = 'admin'
def __str__(self):
# Alternative: return the member's name (ALL_CAPS)
return self.name
Solution 2: Controlling Debug and List Output with __repr__​
While __str__ controls the friendly output, __repr__ controls the official string representation used for debugging, logging collections (like lists and dictionaries), and interactive shell output. Experts often leave __repr__ verbose for debugging but may override it for specific needs.
class DebugStatus(Enum):
ACTIVE = 1
INACTIVE = 0
def __str__(self):
return self.name.lower() # Friendly output
# Override __repr__ for clean list display
def __repr__(self):
# Return a clean, non-class-prefixed string representation
return f"'{self.name}'"
# Usage:
statuses = [DebugStatus.ACTIVE, DebugStatus.INACTIVE]
print(f"String output: {statuses[0]}")
# Output: active (Calls __str__)
print(f"List representation: {statuses}")
# Output: ['ACTIVE', 'INACTIVE'] (Calls __repr__ for each element)
Solution 3: Custom Formatting in f-strings with __format__​
The __format__ method allows you to define specialized formatting based on a format specifier provided in an f-string (e.g., {member:spec}). This is highly advanced and useful for converting Enum values into hex, binary, or lowercase on the fly.
class ConfigFlag(Enum):
READ = 1
WRITE = 2
EXECUTE = 4
def __format__(self, format_spec):
if format_spec == 'hex':
# Format the raw value as hexadecimal
return f"0x{self.value:X}"
elif format_spec == 'lower':
# Format the member name in lowercase
return self.name.lower()
# Fallback to default formatting if specifier is not handled
return super().__format__(format_spec)
# Usage:
flag = ConfigFlag.EXECUTE
print(f"Hex output: {flag:hex}")
# Output: 0x4
print(f"Lowercase output: {flag:lower}")
# Output: execute
Solution 4: Injecting __str__ via Mixins​
To avoid repeating the boilerplate __str__ implementation across multiple Enum classes, you can use a simple mixin that provides the desired behavior.
class ValueStrMixin:
"""Mixin to ensure __str__ always returns the raw value."""
def __str__(self):
return str(self.value)
class SimpleStatus(ValueStrMixin, Enum):
ON = "active"
OFF = "inactive"
class ErrorCode(ValueStrMixin, Enum):
MISSING_PARAM = 400
ACCESS_DENIED = 403
# Usage:
print(f"Status output: {SimpleStatus.ON}")
# Output: active
print(f"Error output: {ErrorCode.ACCESS_DENIED}")
# Output: 403
# Annotation: When SimpleStatus is instantiated, it inherits __str__ from
# ValueStrMixin, ensuring consistent formatting across all inheriting Enums.
