Enumerations and 5-Way Variation
00:00 In the previous lesson, you learned how to determine who is the winner in rock paper scissors. In this lesson, I’ll show you how to use enumerations to reduce the chance of errors in your code, and then add a Spock to your game.
There are a few exceptions but, generally, hard-coded strings and numbers are considered bad practice in programming. Looking back at the last program, there are six instances of the word
"rock", six of
"paper", and six of
"scissors". One little spelling error in any one of those six cases and you’ll have a bug in your code. What’s worse, even if your code is bug free, your user has to keep typing
"scissors". It could get frustrating quickly.
Python supports the concept of an enumeration, or enum for short. This is a way of grouping symbols or values together. For our code, the
"scissors" are all choices that the user can make. An enum grouping those together makes sense.
A similar fix needs to be done to update the
MESSAGES dict. With these changes in place, any spelling error in the word scissors will result in a compiler error. Let me just scroll down to the bottom.
Let’s go through it step by step. Line 46 still asks the user for input. Note the
CHOICES_STR (choices string) variable inside the input prompt. Instead of hard-coding the choices, this string is determined dynamically based on the contents of the
Choice enum. Let me scroll back up to the top to show you where this is done.
Line 10 does a list comprehension. This is a short-form for creating a list by looping over some values. In this case, all the possible choices in the
Choice enumeration are iterated over and for each choice, a string is built.
The string contains the name of the choice, square brackets, and the number of the choice inside of the brackets. The all-caps
CHOICES list will have three strings inside of it:
03:36 Line 11 takes the list created on line 10 and turns it into a single string with the values separated by commas. This string is a readable version of the choices the user will be presented with.
Line 46 prompted the user with the choices string. Line 47 then creates a
Choice enumeration object based on what the user typed in. Two things can go wrong here. One, the thing the user typed in might not convert into an integer, and two, the user might type in an integer that isn’t a valid choice.
Both of these situations raise a
int() function raises a
ValueError if it can’t convert the string it was given into an integer, and the
IntEnum raises a
ValueError if you try to create a
Choice object with a bad value. In either of these cases, the
except clause will run. Line 49 displays an error message, and then line 50 causes the code to continue execution from the top of the loop, giving the user a chance to type something else in.
The random choice the computer makes has to change as well. Previously, you used the
choice() function from the
random module that randomly chose an item from a list. Now that you’re using an
IntNum, it is better to take advantage of a different function from
Remember, though, collections of things in Python are usually zero-indexed. In this case,
len() will return
3. There are three things in the enum. Subtract
1 from the length to get the appropriate upper boundary for the random integer. Line 53 constructs a
Choice object using the random value just determined.
As before, the values for the user and computer are passed to
show_winner(). They used to be strings, but now they are
Choice objects, so the
show_winner() function is going to need some modifications.
Line 27 shows the first example of this. You can get the text representation of an enum by accessing the
.name property on it. What used to be just
user_choice is now
user_choice.name to get the text version of the number the user typed. As the enum named each value with capital letters, I’m also calling
.lower() on the result.
There are several other cases inside of
show_winner() where this kind of thing has to be done as well. All of them are places where user or computer choices were displayed, but the change is the same as line 27.
07:19 Most of the code changes in the last two scripts were kind of neutral. The code was a bit cleaner and a little shorter, but not by much. Where these changes become important is if you want to make the game more complicated.
The switch to enumerations makes life easier as well. To get the new version going, all you need to do is update the
Choice enumeration with lizard and Spock and update the
And then one tiny change, due to my anal retention. I’ve removed the call to
.lower() here on line 38 because Spock is a proper name. It offends me less to have capital-R
"Rock" here than it does to have small-s
"spock". If you wanted to get fancy, you could add a bit of conditional code to deal with both, but I went with lazy instead. With everything in place, you’re ready to go.
09:22 You can see how structuring your code correctly can make certain kinds of changes far simpler. Writing a program is always a trade-off. You can do clever things and possibly spend a lot of time for little value, or you can do obvious things and often make your life painful later when you want to make changes. The more you code, the more you’ll get used to these kinds of decisions and the choice will become more obvious with experience. Next up, I’ll wrap up the course with a quick summary.
Become a Member to join the conversation.