The essentials
Quick reference
One focused task per row. Jump to the related section for complete, working examples.
| Use | Syntax | Examples |
|---|---|---|
| Declare an enum | class Color(Enum): RED = 1 | View examples |
| Look up by value | member = Color(1) | View examples |
| Look up by name | member = Color['RED'] | View examples |
| Read member metadata | name, value = member.name, member.value | View examples |
| Iterate canonical members | members = list(Color) | View examples |
| Declare an alias | CRIMSON = RED | View examples |
| Inspect names including aliases | names = Color.__members__ | View examples |
| Reject duplicate values | @unique | View examples |
| Generate enum values | PENDING = auto() | View examples |
| Create string-compatible members | class Format(StrEnum): JSON = auto() | View examples |
| Create integer-compatible members | class ExitCode(IntEnum): OK = 0 | View examples |
| Declare bit flags | class Permission(Flag): READ = auto() | View examples |
| Combine flags | access = Permission.READ | Permission.WRITE | View examples |
| Test a contained flag | allowed = Permission.WRITE in access | View examples |
| Customize missing-value lookup | _missing_ = classmethod(normalize_missing_value) | View examples |
| Add member behavior | def can_retry(self): return self is State.FAILED | View examples |
| Build an enum dynamically | Level = Enum('Level', ['LOW', 'HIGH']) | View examples |
| Verify enum constraints | @verify(CONTINUOUS) | View examples |
Enums group symbolic names into a distinct type, making states, modes, protocol values, and bit masks harder to confuse with unrelated literals. Prefer Enum when identity and type separation matter, StrEnum or IntEnum only when compatibility with existing string or integer APIs is required, and Flag for values that may be combined. Treat member values as an external contract only when persistence or interoperability actually requires it.
Step by step
Detailed examples
Declare, inspect, and look up enum members
An Enum member is a singleton instance of its enum class. Use dotted access when the name is known in source code, subscription for a dynamic name, and a class call for lookup by value. Iteration preserves definition order and yields canonical members. Plain Enum members compare by identity and do not compare equal to their raw values, preserving separation between domains that happen to use the same underlying value.
from enum import Enum
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
member = Color['GREEN']
print(member is Color.GREEN)
print(Color(3).name, Color.BLUE.value)
print([color.name for color in Color])
print(Color.RED == 1) True
BLUE 3
['RED', 'GREEN', 'BLUE']
FalseChoose deliberately between aliases and unique values
When two names receive the same value, the later name is normally an alias of the first member. Aliases are absent from ordinary iteration but visible in __members__, and by-value lookup returns the canonical first member. This is useful for migrations and compatible vocabulary. Apply @unique when every name must have a distinct value; it checks the completed class and raises ValueError if aliases exist.
from enum import Enum
class Color(Enum):
RED = 1
CRIMSON = 1
BLUE = 2
print(Color.CRIMSON is Color.RED)
print([member.name for member in Color])
print(list(Color.__members__))
print(Color(1).name) True
['RED', 'BLUE']
['RED', 'CRIMSON', 'BLUE']
REDGenerate values with auto and StrEnum
auto() delegates to _generate_next_value_: plain Enum and IntEnum ordinarily generate increasing integers from 1, Flag generates powers of two, and StrEnum generates the lower-cased member name. StrEnum was added in Python 3.11 and is both str and Enum, which helps replace existing textual constants. Some libraries require type(value) is str rather than isinstance(value, str); pass str(member) at those strict boundaries.
from enum import StrEnum, auto
class Format(StrEnum):
JSON = auto()
CSV = auto()
TEXT = 'plain-text'
print(Format.JSON.value)
print(str(Format.TEXT))
print(isinstance(Format.CSV, str))
print([item.value for item in Format]) json
plain-text
True
['json', 'csv', 'plain-text']Use IntEnum only at integer compatibility boundaries
IntEnum members are integers and compare equal to matching int values, making them suitable for replacing legacy numeric constants. That convenience weakens type separation: equal-valued members of unrelated IntEnum classes can compare equal through integer semantics, and ordinary arithmetic returns plain int results. Since Python 3.11, str() on an IntEnum member uses int.__str__. Prefer plain Enum for new domain models unless integer interoperability is a requirement.
from enum import IntEnum
class ExitCode(IntEnum):
OK = 0
RETRY = 75
print(ExitCode.OK == 0)
print(str(ExitCode.RETRY))
result = ExitCode.RETRY + 1
print(result, type(result).__name__)
print(ExitCode(0).name) True
75
76 int
OKRepresent independent options with Flag
Flag members support bitwise union, intersection, exclusive-or, and inversion while preserving the flag type. auto() assigns powers of two so individual members combine without overlapping bits. Flag containment and iteration over a composite value were added in Python 3.11. Use Flag for internal symbolic combinations; choose IntFlag only when the combined value must interoperate with integer-based APIs, and decide explicitly how unknown bits should be handled.
from enum import Flag, auto
class Permission(Flag):
READ = auto()
WRITE = auto()
EXECUTE = auto()
access = Permission.READ | Permission.WRITE
print(Permission.WRITE in access)
print(Permission.EXECUTE in access)
print([item.name for item in access])
print((access & Permission.READ).name) True
False
['READ', 'WRITE']
READNormalize external values with _missing_
Calling an enum class performs by-value lookup and invokes _missing_ when no member is found. Override it as a class method to normalize a documented external representation, returning a member or None. Keep lookup deterministic and narrowly scoped; silently mapping arbitrary invalid values to a default can hide corrupt data. The hook only affects value lookup such as BuildMode('FAST'), not name lookup such as BuildMode['FAST'].
from enum import StrEnum
class BuildMode(StrEnum):
DEBUG = 'debug'
RELEASE = 'release'
@classmethod
def _missing_(cls, value):
if isinstance(value, str):
normalized = value.casefold()
for member in cls:
if member.value == normalized:
return member
return None
print(BuildMode('DEBUG').name)
print(BuildMode('Release').value)
try:
BuildMode('preview')
except ValueError:
print('invalid mode') DEBUG
release
invalid modeAttach domain behavior without extending member enums
Enums are classes, so methods and properties can express behavior shared by their members. Existing enums that define members cannot be subclassed to add more members because that would break their identity and type invariants; share behavior through an empty enum base or ordinary mixin instead. Keep unrelated service logic outside the enum so the symbolic type remains focused.
from enum import Enum
class State(Enum):
PENDING = 'pending'
RUNNING = 'running'
FAILED = 'failed'
COMPLETE = 'complete'
def can_retry(self):
return self is State.FAILED
def can_finish(self):
return self is State.RUNNING
for state in (State.PENDING, State.RUNNING, State.FAILED):
print(state.value, state.can_retry(), state.can_finish()) pending False False
running False True
failed True FalseCreate dynamic enums and validate integer layouts
The functional API is useful when member names come from configuration or generated metadata; its start argument controls the first automatic integer value. Classes created dynamically must remain importable by a stable qualified name if they will be pickled. Python 3.11 added @verify with checks including UNIQUE, CONTINUOUS, and NAMED_FLAGS; @unique remains the broadly compatible way to reject aliases on older supported versions.
from enum import CONTINUOUS, Enum, IntEnum, verify
Level = Enum('Level', ['LOW', 'MEDIUM', 'HIGH'], start=10)
@verify(CONTINUOUS)
class HttpClass(IntEnum):
INFORMATIONAL = 1
SUCCESS = 2
REDIRECTION = 3
print([(item.name, item.value) for item in Level])
print([item.value for item in HttpClass]) [('LOW', 10), ('MEDIUM', 11), ('HIGH', 12)]
[1, 2, 3]Local code tester
Model states and feature flags
Add states, combine capabilities, and compare strict Enum identity with Flag membership.
Press Run to load Python locally.
Sources and further reading
References
Authoritative documentation used to verify and expand this cheat sheet.
- Python Software Foundationenum — Support for enumerationsdocs.python.org
- Python Software FoundationEnum HOWTOdocs.python.org
- Python Software FoundationPEP 435 — Adding an Enum type to the Python standard librarypeps.python.org
- Python Software FoundationData model — Basic customizationdocs.python.org
Help us improve
Found a typo or missing example?
Tell us what would make this cheat sheet clearer, more complete, or more useful.



