Python Enums: Type-Safe Constants for Cleaner Code
Imagine you're building a card game. You need to represent the four suits: hearts, diamonds, clubs, and spades. You could use plain strings like "hearts", but what happens when someone types "Hearts" or "hart"? Your code breaks silently.
Python's `enum` module solves this by letting you define a fixed set of named constants. An Enum (short for enumeration) is a class where each member has a name and a value, and you can't accidentally create invalid members.
In this tutorial, you'll learn to create basic enums, use auto() for automatic values, work with IntEnum and Flag, add methods to enums, and apply practical patterns you'll use in real projects.
How Do You Create a Basic Enum?
An enum is a class that inherits from Enum. Each member is defined as a class attribute with a value. Once created, the members are fixed -- you can't add, remove, or change them.
Each enum member has two key attributes: .name (the string name like "RED") and .value (the assigned value like 1). You can look up members by name with bracket notation Color['RED'] or by value with callable notation Color(1).
How Do You Compare and Iterate Over Enums?
Enums shine when you use them in if statements and loops. You can compare members with == or is, and iterate over all members of an enum class.
# Typos cause silent bugs
status = 'actve' # oops
if status == 'active':
print('Active') # never runs!from enum import Enum
class Status(Enum):
ACTIVE = 'active'
status = Status.ACTIVE
# Status.ACTVE would raise AttributeError!What Are auto(), IntEnum, and @unique?
When the exact value doesn't matter, auto() generates values automatically. IntEnum creates enums whose members behave like integers -- useful when you need to do math or pass them to APIs that expect numbers. The @unique decorator prevents duplicate values.
Can Enums Have Methods?
Since enums are classes, you can add methods and properties to them. This lets you attach behavior directly to each member, keeping related logic together instead of scattering if/elif chains across your code.
What Are Common Enum Patterns in Real Code?
Enums appear everywhere in professional Python code. Here are two patterns you'll encounter often: using enums as dictionary keys, and converting between enums and strings (useful for APIs and databases).
Enums are hashable, so they work perfectly as dictionary keys. This replaces messy if/elif chains with clean, O(1) lookups. When you receive user input as a string, Size(value) converts it back to the enum member (raising ValueError if the value is invalid).
Practice Exercises
Create an Enum called TrafficLight with members RED, YELLOW, and GREEN having string values "stop", "caution", and "go". Then print each member's name and value on separate lines in the format NAME: value.
What will this code print? Think carefully about how enum comparison works and what auto() assigns.
Create an Enum called HTTPStatus with members OK = 200, NOT_FOUND = 404, and SERVER_ERROR = 500. Add a property called is_error that returns True if the value is 400 or above. Print each status and whether it's an error.
This code tries to look up a role from a user-submitted string, but it crashes. Fix the code so it correctly converts the string "admin" into the matching Role enum member and prints its name. Don't change the Role definition.
Create an IntEnum called Permission with READ = 1, WRITE = 2, DELETE = 4, and ADMIN = 7. Write a function check_permissions(user_level, required) that returns True if the user's permission level includes the required permission using bitwise AND (&). Test with the cases shown in the starter code.