Enums (the enum module)
Reviewed & published by Brayan K
An enum is a class that bundles a fixed set of named constant values into one self-documenting type, so a variable can only ever hold one of the choices you defined.
Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
If you have ever passed status="acttive" with a typo and watched it silently break, enums are the fix. They turn loose magic values into named members the editor and interpreter can check.
What You'll Learn in This Lesson
- Defining an Enum subclass with named members
- Reading a member's .name and .value
- Iterating over all members and looking them up
- Letting auto() assign values automatically
- Using IntEnum when members must act like ints
- Combining options with Flag enums
1 Defining an Enum and Reading name / value
Subclass Enum and list your members as NAME = value. Each member is a singleton object you compare by identity:
from enum import Enum
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
favorite = Color.RED
print(favorite) # Color.RED
print(favorite.name) # RED (the identifier you typed)
print(favorite.value) # 1 (the data you assigned)
print(favorite == Color.RED) # True
print(Color.RED == 1) # False -> a member is NOT its raw valueYou can look a member up by value with Color(2) or by name with Color["GREEN"]:
print(Color(2)) # Color.GREEN (lookup by value)
print(Color["BLUE"]) # Color.BLUE (lookup by name)from enum import Enum
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
c = Color.GREEN
print(c) # Color.GREEN
print(c.name, c.value) # GREEN 2
print(Color(3)) # Color.BLUE (by value)
print(Color["RED"]) # Color.RED (by name)
print(Color.RED == 1) # False
# ✅ Expected output:
# Color.GREEN
# GREEN 2
# Color.BLUE
# Color.RED
# False2 Iteration and auto()
Enums are iterable in definition order, which makes them perfect for building menus, validating input, or generating dropdowns. And when the exact numbers do not matter, auto() assigns them for you:
from enum import Enum, auto
class Weekday(Enum):
MONDAY = auto() # 1
TUESDAY = auto() # 2
WEDNESDAY = auto() # 3
# Iterate over every member in order
for day in Weekday:
print(day.name, "=", day.value)
# MONDAY = 1
# TUESDAY = 2
# WEDNESDAY = 3
# Membership and counting work too
print(len(Weekday)) # 3
print(Weekday.MONDAY in Weekday) # TrueWith auto() you only maintain the names. Add, remove, or reorder members without ever renumbering by hand.
from enum import Enum, auto
class Status(Enum):
PENDING = auto()
ACTIVE = auto()
DONE = auto()
# Iterate to build a labeled menu
for s in Status:
print(f"{s.value}. {s.name.title()}")
print("total states:", len(Status))
# ✅ Expected output:
# 1. Pending
# 2. Active
# 3. Done
# total states: 33 IntEnum and Flag
An IntEnum member is an integer, so it sorts and compares like one. Use it for ordered levels such as priorities or log severities:
from enum import IntEnum
class Priority(IntEnum):
LOW = 1
MEDIUM = 2
HIGH = 3
print(Priority.HIGH > Priority.LOW) # True (ordered comparison)
print(Priority.MEDIUM == 2) # True (acts like an int)
print(sorted([Priority.HIGH, Priority.LOW, Priority.MEDIUM]))
# [<Priority.LOW: 1>, <Priority.MEDIUM: 2>, <Priority.HIGH: 3>]A Flag enum lets a single value hold a combination of members using the bitwise | operator — perfect for permissions or feature toggles:
from enum import Flag, auto
class Perm(Flag):
READ = auto() # 1
WRITE = auto() # 2
EXECUTE = auto() # 4
access = Perm.READ | Perm.WRITE # combine two flags
print(Perm.READ in access) # True
print(Perm.EXECUTE in access) # False
print(access) # Perm.READ|WRITEfrom enum import IntEnum, Flag, auto
class Level(IntEnum):
DEBUG = 10
INFO = 20
ERROR = 40
# IntEnum compares like an int
print(Level.ERROR > Level.INFO) # True
print(Level.INFO == 20) # True
class Perm(Flag):
READ = auto()
WRITE = auto()
EXEC = auto()
access = Perm.READ | Perm.WRITE
print(Perm.WRITE in access) # True
print(Perm.EXEC in access) # False
# ✅ Expected output:
# True
# True
# True
# False🎯 Your Turn: Fill in the Blanks
Complete the enum so it auto-numbers its members and reads the right attributes. Replace each ___ and match the expected output.
# 🎯 YOUR TURN: complete the enum
from enum import Enum, ___
class Direction(Enum):
NORTH = ___()
EAST = ___()
SOUTH = ___()
WEST = ___()
d = Direction.EAST
print(d.___) # EAST (the identifier)
print(d.___) # 2 (the auto value)
print(len(Direction)) # 4
# Expected output:
# EAST
# 2
# 4Import: auto. Each member value: auto().
The two prints use d.name (gives EAST) and d.value (gives 2).
Common Errors to Avoid
❌ Comparing a plain Enum to its raw value
if status == 1: # always False for a plain Enum member!
...✅ Compare members to members: if status == Status.ACTIVE: (or use IntEnum if you need int comparisons).
❌ Duplicate values silently become aliases
class Color(Enum):
RED = 1
CRIMSON = 1 # becomes an ALIAS of RED, not a new member✅ Give each member a unique value, or add @enum.unique above the class to raise an error on duplicates.
❌ Trying to add members after definition
Color.YELLOW = 4 # AttributeError: cannot reassign / extend✅ Enums are final. Define every member inside the class body.
🎯 Mini Challenge: Order State Machine
Model an order's lifecycle with an enum, then advance an order to the next state by looking up the following member by value.
from enum import IntEnum
class OrderState(IntEnum):
PLACED = 1
SHIPPED = 2
DELIVERED = 3
def advance(state):
# Move to the next state, or stay put if already final
states = list(OrderState)
idx = states.index(state)
return states[idx + 1] if idx + 1 < len(states) else state
s = OrderState.PLACED
print(s.name) # PLACED
s = advance(s)
print(s.name) # SHIPPED
s = advance(s)
print(s.name) # DELIVERED
s = advance(s)
print(s.name) # DELIVERED (stays final)
# ✅ Expected output:
# PLACED
# SHIPPED
# DELIVERED
# DELIVERED📚 Keep Learning
Go deeper with the official Python documentation:
- enum — Support for enumerations
- Enum HOWTO — practical recipes and patterns
- IntEnum and Flag reference
Frequently Asked Questions
Lesson complete — your constants have names and types now!
You can define an Enum, read .name and .value, iterate over members, auto-number with auto(), compare ordered IntEnum values, and combine options with Flag.
Practice quiz
For a plain Enum Color with RED = 1, what is Color.RED == 1?
- True
- It raises an error
- False
- 1
Answer: False. A plain Enum member is not equal to its raw value, so Color.RED == 1 is False — protecting against stray raw values.
What is the difference between a member's .name and .value?
- .name is the identifier you typed; .value is the data you assigned
- .name is the value, .value is the name
- They are always equal
- .value only exists on IntEnum
Answer: .name is the identifier you typed; .value is the data you assigned. Color.RED.name is the string 'RED' (the identifier); Color.RED.value is the assigned data such as 1.
How do you look up an enum member by its value, e.g. value 2 of Color?
- Color.value(2)
- Color['2']
- Color.get(2)
- Color(2)
Answer: Color(2). Calling the enum like Color(2) performs a value lookup and returns Color.GREEN.
How do you look up an enum member by its name, e.g. 'BLUE'?
- Color('BLUE')
- Color["BLUE"]
- Color.name('BLUE')
- Color.BLUE()
Answer: Color["BLUE"]. Subscript syntax Color["BLUE"] looks a member up by name and returns Color.BLUE.
What value does the first auto() member receive by default?
- 1
- 0
- None
- A random integer
Answer: 1. auto() produces consecutive integers starting at 1 by default, so the first member is 1.
Why might you choose IntEnum over a plain Enum?
- It uses less memory
- It auto-numbers members
- Its members behave like integers, so they compare and sort with < and >
- It allows duplicate values
Answer: Its members behave like integers, so they compare and sort with < and >. IntEnum members ARE integers, so Priority.HIGH > Priority.LOW works and they interoperate with code expecting ints.
What does a Flag enum let you do with the | operator?
- Concatenate names
- Combine several members into one value, like Perm.READ | Perm.WRITE
- Compare values numerically
- Sort the members
Answer: Combine several members into one value, like Perm.READ | Perm.WRITE. Flag enums support bitwise | to combine members, ideal for permissions and feature toggles.
In a plain Enum, what happens if two members are assigned the same value?
- A SyntaxError at import
- Both are silently dropped
- The values are auto-incremented
- The second becomes an alias of the first, not a new member
Answer: The second becomes an alias of the first, not a new member. Duplicate values create an alias: the second name refers to the first member unless @enum.unique forbids it.
Can you add a new member after the enum class is defined, e.g. Color.YELLOW = 4?
- Yes, anytime
- No, enums are final and this raises an error
- Only inside __init__
- Only for IntEnum
Answer: No, enums are final and this raises an error. Enums are final; every member must be defined in the class body, and reassigning/extending raises an error.
What does len(MyEnum) return?
- Always 0
- The largest member value
- The number of members defined in the enum
- The length of the longest member name
Answer: The number of members defined in the enum. Enums are iterable and len() counts their members; a three-member enum returns 3.
Continue this course
- Previous: functools: lru_cache, partial, reduce
- Next: namedtuple & NamedTuple — Lightweight immutable records with named fields and defaults
- Quick reference: Python cheat sheet
Frequently asked questions
What is an enum and why use one instead of plain constants?
An enum (enumeration) is a set of named, constant values grouped under one type. Instead of scattering STATUS_ACTIVE = 1 and STATUS_DONE = 2 across your code, you write a single Color or Status class that lists every valid option. Enums give you a fixed, self-documenting set of choices, real type names in tracebacks, protection against invalid values, and the ability to iterate over all members — none of which loose constants provide.
What is the difference between a member's .name and .value?
Every enum member has two parts. The .name is the identifier you typed — Color.RED.name is the string 'RED'. The .value is the data you assigned — Color.RED.value might be 1 or '#ff0000'. You compare and pass around the member itself (Color.RED), and reach for .name when you need a label and .value when you need the underlying data.
When should I use IntEnum instead of Enum?
Use IntEnum when the members genuinely need to behave like integers — for example comparing priorities with < and >, or interoperating with code or a protocol that expects plain ints. A regular Enum member is NOT equal to its integer value (Color.RED == 1 is False), which is usually what you want for safety. IntEnum trades that safety for int compatibility, so reach for it only when you truly need the numeric behavior.
What does auto() do?
auto() lets the enum assign values for you instead of typing 1, 2, 3 by hand. By default it produces consecutive integers starting at 1, so you focus on the names and never worry about keeping the numbers unique. It is ideal when the actual value does not matter and you only care about distinct, named members.