Hogwarts Sorting Hat with Python

Photo by Clarisse Meyer on Unsplash

Curious about Python? This tutorial will introduce you to the basics of Python programming — including variables, conditionals, and lists — as you build a Hogwarts Sorting Hat. I mean, it’s time they updated to the latest technology…

image via bdcwire.com

Getting started

For your Python development environment, create a new repl with Python (listed under “Popular” languages).

If you haven’t read the Harry Potter series, the Hogwarts Sorting Hat divides the students of Hogwarts into four different houses based on their dominant personality traits: Gryffindor (brave people), Ravenclaw (studious people), Hufflepuff (loyal people), and Slytherin (cunning/ambitious people).

So basically, we’re going to build a personality quiz. If you’re not into Harry Potter, you can still follow along and learn Python code, and maybe change the questions to form another personality quiz (e.g. What Friends character are you?).

Variables

The first thing we’re going to do in our Python repl is declare our variables. A variable is a container for a value, which often changes throughout the course of the program.

I’m going to create a variable for each Hogwarts house, and each variable will store a number that tracks how many answers the user has given that correspond to a particular house.

For instance, a user who picks mostly a’s will be sorted into Gryffindor, since the “a” answers correspond to Gryffindor traits. In this case, the gryffindor variable will be increased (or incremented) by one.

Each variable will start out at zero. Type this code into your repl:

gryffindor = 0
ravenclaw = 0
hufflepuff = 0
slytherin = 0

Strings & user input

Now that our variables are declared, we can ask the user our first question. In our code, we will represent the question as a string. A string is a data type (like a number) that represents letters, words, or phrases in double quotes. Here is the question I want to ask (don’t paste this into your code yet):

"How would you describe yourself? a) brave, b) studious, c) loyal, or d) ambitious?"

I can use Python’s print function to print this string on the page, but I want the user to type a letter to answer my question. Luckily, Python has an input function that I can use to store the user’s answer in a variable. Here’s how I can ask the first question:

q1_answer = input("How would you describe yourself? a) brave, b) studious, c) loyal, or d) ambitious?")

We have just declared a new variable, q1_answer. Whatever the user types in response to the question will be stored in that variable.

After you type the code above into your repl, run the program and see what happens!

Press the “run” button near the top.
After a second, this should appear on the screen!

So cool! It would be nice if the text was more spaced out though, right? Like if we could add in some carriage returns (the technical turn for what happens when you hit the return key)?

The good news is, we can! When we write \n in a string, it’s basically like hitting the return key. Edit your latest line of code to incorporate some carriage returns:

q1_answer = input("How would you describe yourself? \na) brave \nb) studious \nc) loyal \nd) ambitious\n")

Now run your program again:

Nice! Just a like a multiple choice test you’d take in school.

Much better!

Conditionals

OK, so we’ve stored the user’s first answer in q1_answer. But what do we do with it? We need to update the variables with all the houses, right? But how do we know which house variable to update?

Well, I’m writing the quiz to lead to this outcome:

  • Mostly A’s → Gryffindor
  • Mostly B’s → Ravenclaw
  • Mostly C’s → Hufflepuff
  • Mostly D’s → Slytherin

So if the user types “a,” I want to increment (increase) the gryffindor variable. Otherwise, if the user types “b,” increment the ravenclaw variable. Otherwise, if the user types “c,” increment the hufflepuff variable. And otherwise, if the user types “d,” increment the slytherin variable.

It turns out that we can easily translate these methodical sentences into code. By using conditionals, which are comprised of statements with if, elif (else if), and else, we can make the computer only perform certain actions under certain conditions.

For instance, I can write “if the user’s input was ‘a,’ increase the gryffindor variable by one” in Python like this:

if q1_answer == "a":
gryffindor = gryffindor + 1

A few things to note. First of all, the double equals sign == on the first line is not a typo. We already used a single equals sign = to assign the variables their original values (0). To make sure that the computer knows I’m testing for equality (not assigning a new value), I have to use the double equals sign ==.

Make sure you don’t forget the colon at the end of the first line, and the indent at the beginning of the second line! Unlike other programming languages, indents are essential in Python, so be sure to indent after if/elif/else statements.

Continuing through the second line, programmers do operations like gryffindor = gryffindor + 1 so often that there’s a shortcut for it. Instead of repeating the variable name, I can just say gryffindor += 1, which is short for “make gryffindor equal to itself plus one.”

So a better way to start our code would actually be:

if q1_answer == "a":
gryffindor += 1

OK, now we need to add the other options. At this point, we can start saying elif (else if) because we want to attach these statements to the first if statement.

After you’ve added the code above to your repl, continue by adding these lines:

elif q1_answer == "b":
ravenclaw += 1
elif q1_answer == "c":
hufflepuff += 1
elif q1_answer == "d":
slytherin += 1

Make sure that all your if/elif statements have the same indentation (none), and that the variable increment statements are all indented.

Edge case: what if the user makes a typo and writes something other than one of the letter options? Let’s add a final else clause as a catch-all for any other answer that gives an error message:

else:
print("Sorry, I don't understand that answer.")

Congratulations, you’ve just written a set of conditional statements!

Before you proceed, make sure your code is indented just like this (otherwise you will have problems later):

if q1_answer == "a":
gryffindor += 1
elif q1_answer == "b":
ravenclaw += 1
elif q1_answer == "c":
hufflepuff += 1
elif q1_answer == "d":
slytherin += 1
else:
print("Sorry, I don't understand that answer.")

Adding more questions

Disclaimer: This section will include reusing parts of our code (possibly by copying and pasting!). Ordinarily, good developers never copy and paste code, and they wrap up reusable parts of their code into functions. But we’ll skip over functions for now, although you can challenge yourself to add them later.

We’re going to add two more questions to our quiz using the same general procedure as before. Feel free to modify these questions and answers to either add your own creative touch or to suit the focus of your particular quiz.

In question two, we store our result in q2_answer and increment the corresponding Hogwarts house variable:

q2_answer = input("What can you be found doing on the weekends? \na) Going on adventures \nb) Doing my homework \nc) Spending time with family or friends \nd) Plotting revenge on my enemies\n")
if q2_answer == 'a':
gryffindor += 1
elif q2_answer == 'b':
ravenclaw += 1
elif q2_answer == 'c':
hufflepuff +=1
elif q2_answer == 'd':
slytherin +=1
else:
print("Sorry, I don't understand that response.")

In question three, we store our result in q3_answer and increment the corresponding Hogwarts house variable:

q3_answer = input("What would you do if the Dark Lord was going to invade your school? \na) Fight him \nb) Look up some good defensive curses in a book \nc) Stand by my friends no matter what \nd) Help the Dark Lord invade the school as an inside spy\n")
if q3_answer == 'a':
gryffindor += 1
elif q3_answer == 'b':
ravenclaw += 1
elif q3_answer == 'c':
hufflepuff +=1
elif q3_answer == 'd':
slytherin +=1
else:
print("Sorry, I don't understand that response.")

Feel free to add in your own questions before sorting the user into their Hogwarts house!

Sorting the user into their house

Now that we’ve been incrementing our gryffindor, ravenclaw, hufflepuff, and slytherin variables, hopefully one of those variables is larger than the other to reflect where the user will eventually be sorted.

For each of the houses, we have to first determine if that house variable (e.g. gryffindor) has a greater number than the variable for every other house has. This necessity will result in some very clunky conditional statements.

To determine if a user belongs in Gryffindor, we have to say:

if gryffindor > ravenclaw and gryffindor > hufflepuff and gryffindor > slytherin:
print("GRYFFINDOR!!!!!!")

See what I meant about clunky? As always, be careful with the indentation.

We can continue with the other houses using elif statements. After typing the above code into your repl, add the following code:

elif ravenclaw > gryffindor and ravenclaw > hufflepuff and ravenclaw > slytherin:
print("RAVENCLAW!!!!!!")
elif hufflepuff > gryffindor and hufflepuff > ravenclaw and hufflepuff > slytherin:
print("HUFFLEPUFF!!!!!!")
elif slytherin > gryffindor and slytherin > ravenclaw and slytherin > hufflepuff:
print("SLYTHERIN!!!!!!")

But we only had three questions, so what if none of the variables is greater than all the others? What if the user picked one Gryffindor answer, one Ravenclaw answer, and one Slytherin answer?

We should use an else statement as a catch-all for other results:

else:
print("Too difficult to decide... Maybe this quiz needs more questions.")

But that’s a disappointing result for the user who took the time to take your quiz. We could at least tell them how they scored. To do that, we’re going to use a new data type called a list.

Putting our houses in a list

We want to be able to quickly tell the user any house that they selected an option for. To do that, we’re going to check the value of each house variable to csee if it’s greater than zero. If it is greater than zero, we’re going to add the house name to a data type called a list, which is exactly what it sounds like.

First, we need to initialize (or create) an empty list. Remember that we are still working under the else branch, so make sure your code is indented as you paste it in!

houses = []

Now we have a variable called houses that contains an empty list.

Next, we want to check each of our variables — gryffindor, ravenclaw, hufflepuff, and slytherin--to see which ones are greater than zero. If a variable is greater than zero, I want to add that house name to our houses list, because it means the user selected at least one option for that house.

To add “Gryffindor” to our list if it’s greater than zero, I can say:

if gryffindor > 0:
houses.append("Gryffindor")

I can do the same with the other houses, but I don’t want to use elif this time. elif will only run if the first if statement doesn’t, and I want ALL the statements to run. After you paste in the code above, continue adding in the following code:

if ravenclaw > 0:
houses.append("Ravenclaw")
if hufflepuff > 0:
houses.append("Hufflepuff")
if slytherin > 0:
houses.append("Slytherin")

Again, be careful with the indentation — make sure all the if statements are indented the same, and that the append statements are all indented underneath each if statement.

Now houses should contain all the potential houses that the user scored points for. The last thing I want to do is tell the user all the possible houses they could have been in. I’ll say:

print("You could have been in...")

And now I want to go through the list (called iterating over the list) and print every house that the list contains. All I have to do is say:

for house in houses:
print(house)

Watch the indentation!

This code will store each house in the list houses as the temporary variable house in order, and then it will print the house.

Remember that we have been working under the else statement, so if you want this code to only execute when there is no other option for the user, make sure your code is indented accordingly!

Test out your code to see if it works. Try landing in one house or triggering the else branch that lists all the houses!

Troubleshoot any error messages that come up. If there are no error messages, but your program is still acting weird, double-check the indentation. If all else fails, compare your code to the solution code.

Congratulations on writing a fully functional Python application!

Challenge extensions

  1. Add more questions to your quiz to give a more accurate result.
  2. Find out what a function is in Python and refactor your code so that the answer to each question goes into a function that increments the appropriate variable.
  3. Find out what a dictionary is in Python and use one to keep track of the counts for each house variable. Then loop through the dictionary to find the variable with the highest count at the end.
  4. Write a new Python personality quiz that tests something else! Make it about your own favorite book, movie, TV show, etc.
  5. Write a Python trivia quiz about a topic you know a lot (or a little!) about.