Python
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
133: Enums for Named Constants
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
Enumandauto. - Create the
LightColorEnum. - Update the
change_lightfunction to accept and returnLightColormembers instead of strings. - Test the function by calling it with
LightColor.GREEN.
There are no comments for now.