Skip to Content
Course content

133: Enums for Named Constants

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've spent a lot of my career debugging issues that turned out to be nothing more than a typo in a string. You know the ones: one part of the code checks for "pending", but another part sends "Pending" with a capital P, or maybe someone wrote "pnding". It's a nightmare because the code doesn't technically "crash"—it just silently fails to enter an if block, and you spend two hours staring at a debugger wondering why your logic isn't firing.

The danger of magic strings

Let's look at how I'd normally start building a simple order tracking system. I'll probably just use strings to keep things moving quickly. Here is a snippet of how I might handle order status updates:

def update_order_status(order, status):
    if status == "shipped":
        print("Sending notification email to customer...")
    elif status == "delivered":
        print("Closing the order ticket.")
    # ... more logic here

Now, here is where I usually trip up. I'll go to another part of the app and call that function, but I'll make a tiny mistake:

# Oops, I capitalized the 'S'
update_order_status(my_order, "Shipped") 

If you ran this, nothing would happen. No error, no crash, just... silence. The if statement failed because "Shipped" != "shipped". In a professional codebase, this is unacceptable. We need a way to define a fixed set of "named constants" that the IDE can help us with.

Grouping constants with Enum

This is exactly why Python has the enum module. Instead of floating strings, we create a class that inherits from Enum. This groups our related constants together and ensures we are using the exact same objects throughout the app.

from enum import Enum

class OrderStatus(Enum):
    PENDING = 1
    SHIPPED = 2
    DELIVERED = 3
    CANCELLED = 4

# Now we use the Enum member, not a string
def update_order_status(order, status):
    if status == OrderStatus.SHIPPED:
        print("Sending notification email to customer...")
    elif status == OrderStatus.DELIVERED:
        print("Closing the order ticket.")

update_order_status(my_order, OrderStatus.SHIPPED)

The beauty here is that if I try to type OrderStatus.SHIPED (with one 'p'), Python will throw an AttributeError immediately. I'd rather the program crash during development than silently fail in production.

Letting Python handle the values

You'll notice I assigned numbers (1, 2, 3) to those statuses. To be honest, I don't actually care if SHIPPED is 2 or 42; I just need it to be unique. Manually numbering constants is tedious and error-prone if you have a list of fifty items.

Python provides a helper called auto() for this. It tells Python, "Just give this a unique value, I don't care what it is."

from enum import Enum, auto

class OrderStatus(Enum):
    PENDING = auto()
    SHIPPED = auto()
    DELIVERED = auto()
    CANCELLED = auto()

Using auto() makes the code cleaner and tells other engineers that the specific value of the constant isn't important—only the name is. I always use auto() unless the values have a specific meaning (like HTTP status codes where 404 actually means something specific).




📋 Practical Task

Refactoring the Traffic Light Controller

You are working on a simulation for a traffic light system. Currently, the code uses strings, which is causing bugs in the timing logic. Refactor the following code to use an Enum called LightColor with the members RED, YELLOW, and GREEN.

# Current buggy code
def change_light(current_color):
    if current_color == "green":
        return "yellow"
    elif current_color == "yellow":
        return "red"
    elif current_color == "red":
        return "green"

# This call is currently failing because of a typo: "Grene"
# print(change_light("Grene")) 

Your task:

  • Import Enum and auto.
  • Create the LightColor Enum.
  • Update the change_light function to accept and return LightColor members instead of strings.
  • Test the function by calling it with LightColor.GREEN.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.