4

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?

3
  • Why not status in Status?
    – jonrsharpe
    Commented May 11, 2020 at 6:40
  • status is currently a string, so that would fail I believe. Should I set status to be one of Status.Starting, Status.InProgress, and Status.Complete instead of "Starting", "In-progress" and "Complete" ?
    – user35734
    Commented May 11, 2020 at 12:55
  • You can just call Status(status) then, it throws a ValueError if invalid.
    – jonrsharpe
    Commented May 11, 2020 at 12:58

2 Answers 2

6

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.

2
  • 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
    Commented May 12, 2020 at 2:20
  • 1
    @user35734: Because Enum members are singletons (only one is ever created) it is recommended to do if status is States.Starting (i.e. use is instead of ==). Also, since Enum members are constants, it is recommended to have the member name be all caps -> Status.STARTING. Commented May 12, 2020 at 3:24
2

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)
                )
2
  • 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
    Commented 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. Commented May 11, 2020 at 22:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.