Exploring Enumerations in Python 3.8 to 3.12: An Overview
Written on
Introduction to Enumerations
Enumeration is a specific data type utilized in programming that consists of a set of named constants. Unlike languages such as C++ or Java, which have their own syntax for enumerations, Python introduces this concept through the Enum class, allowing for the creation of custom enumerations.
from enum import Enum
class TrafficLightColor(Enum):
RED = 0
YELLOW = 1
GREEN = 2
Terminology:
- Enumeration (enum): TrafficLightColor
- Enumeration members: TrafficLightColor.RED, TrafficLightColor.YELLOW, TrafficLightColor.GREEN
- Member names: RED, YELLOW, GREEN
- Member values: 0, 1, 2
It's crucial to note that specific features are tied to certain Python versions, such as StrEnum introduced in Python 3.11 or the integration of dataclass with Enum in Python 3.12.1.
Strong Typing
By using enumerations, you can create a custom data type that limits the possible values of other variables. For example, if we define traffic light colors as variables:
RED = 0
YELLOW = 1
GREEN = 2
In this case, we have three integer variables. A variable to hold the light value will also be of type int:
light: int = RED
Given that int can hold many values beyond 0, 1, and 2, there is a risk of assigning an incorrect value.
With the Enum class, we can ensure that the variable is restricted to specific values:
light: TrafficLightColor = TrafficLightColor.RED
Important Note: While assigning a value outside of TrafficLightColor won’t trigger an error due to Python's dynamic typing, there are still significant advantages:
- Enhanced code readability.
- Better support from IDEs like PyCharm.
- Strong typing verification can be performed using the MyPy tool.
Iterating Over Members
You can seamlessly iterate through all values of an enumeration using the for … in … construct:
for color in TrafficLightColor:
print(color, color.name, color.value)
Accessing Members by Value
You can retrieve an enum member using the value with the (…) operator, like so:
print(TrafficLightColor(0))
print(TrafficLightColor(1))
print(TrafficLightColor(2))
Passing an invalid value will raise a ValueError:
print(TrafficLightColor(3)) # ValueError: 3 is not a valid TrafficLightColor
Accessing Members by Name
Members can also be accessed by their names using the index […] operator:
print(TrafficLightColor["RED"])
print(TrafficLightColor["YELLOW"])
print(TrafficLightColor["GREEN"])
Unique Set of Values
When defining enumeration members, each name must be unique, though values can repeat. For instance, both RED and YELLOW can have the same value:
from enum import Enum
class TrafficLightColor(Enum):
RED = 0
YELLOW = 0
GREEN = 1
In certain contexts, allowing duplicate enum values might be acceptable. To enforce unique values, you can use the @unique decorator:
from enum import Enum, unique
@unique
class TrafficLightColor(Enum):
RED = 0
YELLOW = 1
GREEN = 2
Automatic Value Assignment
If you prefer not to specify values manually, you can use the auto() method to automatically assign distinct values:
from enum import Enum, auto
class TrafficLightColor(Enum):
RED = auto()
YELLOW = auto()
GREEN = auto()
You can also mix explicit values with auto():
class TrafficLightColor(IntEnum):
RED = 10
YELLOW = auto()
GREEN = auto()
Important Note: When storing values in formats like YAML or JSON, explicit values are recommended to avoid renumbering, which could lead to unexpected behaviors.
IntEnum
IntEnum enhances Enum by adding linear ordering to the enumeration values, allowing for comparisons based on assigned integers:
from enum import IntEnum
class Priority(IntEnum):
Low = 10
Medium = 50
High = 100
print(Priority.Low < Priority.High) # True
print(Priority.Low > Priority.High) # False
You can also compare enumeration values with integers:
print(Priority.Low < 30) # True
print(Priority.High < 30) # False
Using Flags
The Flag class is another extension of Enum, enabling the use of multiple values as a set of binary values:
from enum import Flag, auto
class Switches(Flag):
TurnedOn = auto()
Sound = auto()
Microphone = auto()
state = Switches.TurnedOn | Switches.Sound
for s in Switches:
print(s, '-->', bool(s & state))
StrEnum
Introduced in Python 3.11, StrEnum supports string values with features similar to Enum:
class TrafficLightColor(StrEnum):
RED = auto()
YELLOW = auto()
GREEN = auto()
Syntactic Sugar
A more compact syntax allows the definition of enumerations in one line:
TrafficLightColor = Enum("TrafficLightColor", ["RED", "YELLOW", "GREEN"])
While this saves space, IDE support might be limited, such as in PyCharm.
Dataclass Support
From Python 3.12, you can combine dataclass with Enum to create enumerations for complex objects:
from dataclasses import dataclass
from enum import Enum, auto
@dataclass
class ColorData:
color: str
red: int
green: int
blue: int
class TrafficLightColor(ColorData, Enum):
RED = "red", 200, 0, 0
YELLOW = "yellow", 255, 255, 0
GREEN = "green", 0, 200, 0
Summary
Enumerations can significantly enhance code readability and self-documentation. Although mastering all features may take time, developers will eventually recognize the numerous advantages of using enumerations.
What to Expect in Python 3.12 - This video discusses the upcoming features in Python 3.12, including enhancements to enumerations.
What's New in Python 3.9? - This video provides an overview of the new features introduced in Python 3.9, including updates to the Enum class.