Get Quizzical in Python

Introducing Python class

In this post we will build a simple quiz app that you can run on the console or on your phone or tablet (I tested it with Pydroid 3 app). The questions come from files and so you can create your own question bank.

We will of course randomize the questions to make it unpredictable. A quiz application is the best way to test your knowledge in a subject.

A class introduction

A class in object-oriented programming is a template for creating objects. The template consists of properties and member functions based on the tasks that a class is designed to perform.

The properties are the variables declared in the class and the members are the functions designed to operate on the variables. The properties and functions are accessible to the program only through the an object, also called instance, of that class.

The parameter self associates the properties and members of a class to its object (or instance) when it is created. They are called instance variables and functions.

Question class

We will write a class Question, which will encapsulate a question with its options and the right answer. The init(self) function is a class constructor. It initialises variables to defaults - question and answer to a string and options to an empty list.

class Question:
    def __init__(self):
        self.question = ''
        self.options = []
        self.answer = ''
    def set_question(self, q):
        self.question = q

    def set_options(self, opts):
        self.options = opts

    def set_answer(self, ans):
        self.answer = ans

    def get_question(self):
        return self.question
    def get_options(self):
        return self.options
    def get_answer(self):
        return self.answer
    def __repr__(self):
        opts = ''
        for index, opt in enumerate(self.options):
            opts += str(index + 1) + " " + opt + "\n"
        return f'\nQuestion. {self.question}\n{opts}'

It has setter and getter methods to modify and access the variables. There is a repr dunder method that returns a string representation of the object. We have used it to display the question and its options to the user.

QuestionBank

We will write another class QuestionBank to store the Question objects in a list.

class QuestionBank:
    def __init__(self):
        self.bank = []

    def add_question(self, question):
        self.bank.append(question)
    def get_bank(self):
        return self.bank

It has just two methods, one for adding the Question objects and the other to retrieve the list of Question objects.

Quiz

The Quiz class encapsulates two tasks:

  • displaying the question and
  • checking if the user selection is correct
class Quiz:
    def __init__(self):
        self.question = None
        self.correct = False

    def set_question(self, q):
        self.question = q

    def display_question(self):
        print(self.question)

    def check_answer(self, input):
        opts = self.question.get_options()
        ans = opts[int(input) - 1]
        if ans == self.question.get_answer():
            self.correct = True

    def get_correct(self):
        return self.correct

The Program

In the main() method, we list the files containing the questions and shuffle them before building the question bank.

The play() method actually runs the show and keeps the score for the player. The score is displayed at the end of the quiz.

import os
import random
# class declarations
class Question:
    def __init__(self):
        self.question = ''
        self.options = []
        self.answer = ''
    def set_question(self, q):
        self.question = q

    def set_options(self, opts):
        self.options = opts

    def set_answer(self, ans):
        self.answer = ans

    def get_question(self):
        return self.question

    def get_options(self):
        return self.options

    def get_answer(self):
        return self.answer

    def __repr__(self):
        opts = ''
        for index, opt in enumerate(self.options):
            opts += str(index + 1) + " " + opt + "\n"
        return f'\nQuestion. {self.question}\n{opts}'

class QuestionBank:
    def __init__(self):
        self.bank = []

    def add_question(self, question):
        self.bank.append(question)
    def get_bank(self):
        return self.bank

class Quiz:
    def __init__(self):
        self.question = None
        self.correct = False

    def set_question(self, q):
        self.question = q

    def display_question(self):
        print(self.question)
    def check_answer(self, input):
        opts = self.question.get_options()
        ans = opts[int(input) - 1]
        if ans == self.question.get_answer():
            self.correct = True
    def get_correct(self):
        return self.correct

# build question bank
def build_question_bank(file_list):
    bank = QuestionBank()
    for file in file_list:
        f = open(os.getcwd()+'/files/'+file, 'r', encoding='utf8')
        while(True):
            line = f.readline()
            if line == '':
                break
            q_tokens = line.rstrip().split('|')
            _question = q_tokens[0]
            _options = [x for x in q_tokens[1].split(",")]
            _answer = q_tokens[2]
            question = Question()
            question.set_question(_question)
            question.set_options(_options)
            question.set_answer(_answer)
            bank.add_question(question)
        f.close()
    return bank
def play(bank):
    questions = bank.get_bank()
    random.shuffle(questions)
    score = 0
    for q in questions:
        quiz = Quiz()
        quiz.set_question(q)
        quiz.display_question()
        ans = input("Type your answer: ")
        quiz.check_answer(ans)
        score += 1 if quiz.get_correct() == True else 0
    return score
def main():
    # get file list
    file_list = os.listdir('./files')
    random.shuffle(file_list)
    bank = build_question_bank(file_list)
    score = play(bank)
    print(f'\nYou scored {score} out of {len(bank.get_bank())}\n')
if __name__ == '__main__':
    main()

Exercise

  • Take user name from input and display score against it.
  • Show which questions are answered correctly.
  • Add more topics and questions

Enjoy coding and questioning!