Python Tutorial
Enums in Python
Some values come from a small fixed set: order status (pending, paid, shipped), user role (student, instructor, admin), day of week. Using raw strings like "shiped" invites typos that no tool catches. An enumeration defines the allowed values once as named constants.
This lesson covers Enum, auto(), StrEnum and IntEnum, Flag for combinable permissions, adding methods to enums, and using enums with match.
Defining and Using Enums
Subclass enum.Enum and list members as class attributes. Each member has a name and a value. Access members as Status.PAID, by value Status("paid") or by name Status["PAID"]. Members are singletons: compare with is or ==. Iterating the class yields members in definition order.
auto(), StrEnum and IntEnum
auto() assigns values automatically. StrEnum (3.11+) members are also strings — they serialise naturally to JSON and compare equal to their string values; with auto() the value is the lowercase member name. IntEnum members are integers. Plain Enum members are deliberately not equal to raw values, which catches mix-ups.
Flag for Combinations
enum.Flag members can be combined with | and tested with in — ideal for permissions: Permission.READ | Permission.WRITE.
Methods and Pattern Matching
Enums are classes, so they can have methods and properties, for example Status.can_cancel(). They work well with match statements to handle each state explicitly.
Examples
Defining, accessing and iterating an Enum
from enum import Enum
class Status(Enum):
PENDING = "pending"
PAID = "paid"
SHIPPED = "shipped"
CANCELLED = "cancelled"
s = Status.PAID
print(s, s.name, s.value)
print(Status("shipped"), Status["PENDING"])
print([m.name for m in Status])
print(s is Status.PAID, s == "paid")
try:
Status("shiped")
except ValueError as e:
print("ValueError:", e)
Status.PAID PAID paid
Status.SHIPPED Status.PENDING
['PENDING', 'PAID', 'SHIPPED', 'CANCELLED']
True False
ValueError: 'shiped' is not a valid Status
auto(), StrEnum, IntEnum and JSON
import json
from enum import Enum, IntEnum, StrEnum, auto
class Color(Enum):
RED = auto()
GREEN = auto()
class Role(StrEnum):
STUDENT = auto()
ADMIN = auto()
class Priority(IntEnum):
LOW = 1
HIGH = 3
print(Color.RED.value, Color.GREEN.value)
print(Role.ADMIN, Role.ADMIN == "admin", json.dumps({"role": Role.STUDENT}))
print(Priority.HIGH > Priority.LOW, Priority.HIGH + 1, sorted([Priority.HIGH, Priority.LOW]))
1 2
admin True {"role": "student"}
True 4 [<Priority.LOW: 1>, <Priority.HIGH: 3>]
Flag permissions, enum methods and match
from enum import Enum, Flag, auto
class Permission(Flag):
READ = auto()
WRITE = auto()
DELETE = auto()
editor = Permission.READ | Permission.WRITE
print(Permission.WRITE in editor, Permission.DELETE in editor)
class OrderStatus(Enum):
PENDING = "pending"
SHIPPED = "shipped"
DELIVERED = "delivered"
def can_cancel(self):
return self is OrderStatus.PENDING
def message(status):
match status:
case OrderStatus.PENDING:
return "We are preparing your order."
case OrderStatus.SHIPPED:
return "Your order is on the way."
case OrderStatus.DELIVERED:
return "Delivered. Enjoy!"
for st in OrderStatus:
print(f"{st.value:<10} cancel={st.can_cancel()!s:<5} {message(st)}")
True False
pending cancel=True We are preparing your order.
shipped cancel=False Your order is on the way.
delivered cancel=False Delivered. Enjoy!
Common Mistakes
- Comparing plain Enum members with raw strings (Status.PAID == "paid" is False) — use StrEnum or .value.
- Using magic strings and numbers instead of enums for fixed sets of values.
- Defining two members with the same value, which silently creates an alias; use @enum.unique to prevent it.
- Storing enum names in a database and later renaming members.
Key Points to Remember
- Enums define named constants for fixed sets of values.
- Access members by attribute, value or name; iterate the class.
- auto() generates values; StrEnum and IntEnum behave like str/int.
- Flag supports combinable options with | and in.
- Enums can have methods and work naturally with match.
Practice the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.