Python’s enum module lets you give a fixed set of values meaningful names. Use Enum when members should remain distinct from ordinary integers or strings; choose IntEnum or StrEnum when compatibility with legacy numeric or text values is intentional; and use Flag or IntFlag when options need to be combined with bitwise operations.
What is an enum in Python?
An enumeration is a set of symbolic names, called members, bound to values. Python’s enum module provides a way to represent a defined set of choices—such as a status, color, or permission—instead of scattering unexplained constants through a program. The standard library describes an enumeration as “a set of symbolic names (members) bound to unique values.” Python 3.13 enum documentation
How to define and look up enum members
Import Enum and define members as class attributes. The assigned values may be integers, strings, or other suitable objects.
from enum import Enum
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
favorite = Color.RED
There are two common lookup forms. Call the enum class with a value to find the corresponding member; use indexing with a member’s name to find it by name.
#1 Best Overall
by_value = Color(1) # Color.RED
by_name = Color["RED"] # Color.RED
These lookups answer different questions: Color(1) resolves a value, while Color["RED"] resolves a name. If the requested value or name is not defined, lookup fails rather than inventing a member. See the Python Enum HOWTO for more examples.
Which Python enum type should you use?
| Need | Type | Trade-off |
|---|---|---|
| Named choices that should stay distinct from primitive values | Enum |
Preserves separation from unrelated integers and strings. |
| Compatibility with legacy integer constants | IntEnum |
Behaves like an integer and can compare equal to matching integers or members of other integer enum classes. Arithmetic can return a plain int. |
| Compatibility with string constants | StrEnum |
Behaves like a string; string operations produce plain str values, and exact-type checks may require conversion. |
| Options that can be combined, without integer interoperability | Flag |
Bitwise operations combine members as flags. |
| Combinable options that also interoperate with integers | IntFlag |
Supports bitwise combinations and integer use; non-bitwise operations can lose enum membership, and invalid values depend on flag-boundary behavior. |
For new domain concepts, start with plain Enum unless the surrounding API genuinely requires integer or string compatibility. That separation can prevent values that happen to match from being treated as interchangeable.
How Enum differs from IntEnum
With plain Enum, a member is not simply its underlying primitive value. This is useful when two concepts should remain different even if their stored values match.
Rank #2
from enum import Enum, IntEnum
class Priority(Enum):
HIGH = 1
class LegacyPriority(IntEnum):
HIGH = 1
Priority.HIGH == 1 # False
LegacyPriority.HIGH == 1 # True
IntEnum is intended for compatibility with code that already expects integers. That convenience has a cost: matching values can compare equal across distinct integer enum classes, weakening the distinction between domains. Also, integer arithmetic does not preserve enum membership.
result = LegacyPriority.HIGH + 1
# result is an int, not a LegacyPriority member
Use IntEnum when integer behavior is part of the interface, not merely because numbers are convenient to write.
When to use StrEnum
StrEnum provides enum members that also behave as strings, making it useful when an API or existing code expects named text constants.
from enum import StrEnum
class State(StrEnum):
READY = "ready"
RUNNING = "running"
State.READY == "ready" # True
String operations produce an ordinary string rather than an enum member. Some APIs also check for an exact str type instead of accepting string subclasses; at such a boundary, pass str(member) if needed. Because StrEnum can compare equal to strings, use it only when that interchangeability is appropriate for your domain.
How to combine enum flags
Use Flag or IntFlag when each option represents an independent bit that can be combined. With auto(), flag values are assigned as powers of two, allowing each member to represent a distinct bit.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
from enum import Flag, auto
class Permission(Flag):
READ = auto()
WRITE = auto()
EXECUTE = auto()
access = Permission.READ | Permission.WRITE
if access & Permission.READ:
print("Read is allowed")
The bitwise OR (|) combines options, and AND (&) checks whether an option is present. Use independent bit values; ordinary consecutive values do not represent separate bits reliably.
Flag versus IntFlag
Flag keeps combinations in the flag-enum model. Choose IntFlag when the combined options must also work with integers, such as when interfacing with an API that uses integer bitmasks. As with IntEnum, integer interoperability can blur distinctions, and non-bitwise operations may produce a plain integer instead of an enum member.
Decide how to handle unknown bits
A flag value may contain bits that do not correspond to a declared member. Python’s FlagBoundary controls how such values are treated. Pick the behavior that suits the interface—for example, whether unfamiliar bits should be preserved or rejected—rather than assuming every value is a known combination. The available boundary behavior and its defaults depend on the flag type; consult the enum API reference for the target Python release.
Python version compatibility
The enum module has been part of Python since 3.4, but not every enum feature is available in every release. Check the interpreter used in deployment before relying on newer APIs.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteBest Value
| Python version | Relevant enum additions or changes |
|---|---|
| 3.4 | The enum module was added. |
| 3.11 | StrEnum, EnumCheck, ReprEnum, FlagBoundary, and related helpers were added. The documentation also records changes to str() behavior for IntEnum and IntFlag, and to flag inversion. |
| 3.12 | Dataclass support for enums was added. |
| 3.13 | EnumDict, _add_alias_(), and _add_value_alias_() were added. |
These version details are documented in the Python 3.13 enum API reference. If your code must run on an older interpreter, avoid newer types and helpers unless you provide a compatible alternative.
Choosing a persistence or serialization format
Enum lookup mechanics do not establish one universally safe way to store enum values. Choose a representation based on the compatibility requirements of the data: changing member names or values may affect systems that persist those details. If stored data must survive code or schema changes, define and maintain that representation as part of the application’s contract rather than relying on an enum type alone.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

