I have a string variable named status in my code that can take on three values "Starting", "In-progress", and "Complete". A friend of mine said it was good practice to enforce that status has one of those three values by using an enum. What is the best practice way to do this? (And for what it's worth, is an enum the right tool to use here?)
I've tried :
class Status(Enum):
Starting = "Starting"
InProgress = "In-progress"
Complete = "Complete"
and then in my code I have assert statements as so:
assert(status in Status._value2member_map_)
Is this the right way to do it, or is there something else better?
2 Answers 2
Change your code to use the enum throughout - this is a prime example of where enums shine. If you continue to use a string, you'll have validations strewn throughout your code (which is a Bad Thing), and if you ever add a new status it will be a pain to update everything.
If this value is entered by the user (not likely in this scenario given the connotation, but useful in others), then take the string input from the user and convert it to the enum as soon as possible. That way you still use the enum throughout the domain-specific code and the only reference to the status
as a string is in the UI layer.
-
Thank you! When conditioning on the status (say to check if the process is starting), should I just be doing the following: status == Status.Starting or is there a better way to go?user35734– user357342020年05月12日 02:20:34 +00:00Commented May 12, 2020 at 2:20
-
1@user35734: Because
Enum
members are singletons (only one is ever created) it is recommended to doif status is States.Starting
(i.e. useis
instead of==
). Also, sinceEnum
members are constants, it is recommended to have the member name be all caps ->Status.STARTING
.Ethan Furman– Ethan Furman2020年05月12日 03:24:56 +00:00Commented May 12, 2020 at 3:24
Does your code accept strings, and do you just want to make sure those strings are valid as enums? Or does your code only accept enums, and a string would be an error?
To check if an enum is acceptable:
def some_func(enum_choice):
if enum_choice not in Status:
raise ValueError('%r is not valid; possible choices: %r' %
(enum_choice, list(Status)
)
If you want to support strings as well as enums:
def some_func(choice):
try:
choice = Status(choice)
except ValueError:
# more informative error message
raise ValueError('%r is not valid; possible choices: %r' %
(enum_choice, list(Status)
)
-
I have a status variable which is referenced in a number of places throughout the code. Currently, status is a string value, and the only values I've set it to are "Starting", "In-progress", and "Complete". That said, if it is better for status to be, say, an enum value, I would be fine with changing the type of status.user35734– user357342020年05月11日 04:52:33 +00:00Commented May 11, 2020 at 4:52
-
1@user35734: Yes, it is better to just make it an enum -- however, if you don't use a static type checker (or if you're paranoid ;) you'll still need the first check.Ethan Furman– Ethan Furman2020年05月11日 22:28:57 +00:00Commented May 11, 2020 at 22:28
status in Status
?Status(status)
then, it throws a ValueError if invalid.