← Apps with Gradio

A class for questions

Store each question as an object of your own class, Question, with a check method, so each question knows how to mark itself.

Big apps are built from objects that look after themselves: a question that knows its answer and how to give feedback is easier to reuse than loose dictionaries.

Optional. Last lesson each question was a dictionary, and mark did all the work. A class is a kind of object you design yourself: class Question says what every question has (its text, choices and answer, stored as self.text, self.choices, self.answer) and what it can do (its methods: check(guess) and feedback(guess)). Question("What is 7 x 8?", [...], "56") makes one. If you did Objects with turtles, this is the same idea.

PredictRead the code and say what it will do before you run anything. A wrong guess is fine: it shows you what to look for.

Predict

quiz.py
class Question:
    def __init__(self, text, choices, answer):
        self.text = text
        self.choices = choices
        self.answer = answer

    def check(self, guess):
        return guess == self.answer

    def feedback(self, guess):
        if self.check(guess):
            return "Right: " + self.text
        return "Not quite: " + self.text + " The answer is " + self.answer + "."


q = Question("What is 7 x 8?", ["54", "56", "64"], "56")
print(q.check("54"))
print(q.feedback("56"))

q.check("54") runs the check method for this question, with self being q. What does it compare?

What does the first print show?

RunRun it and compare the result with your prediction.

Run

Run it: the same quiz as last lesson, but each question marks itself. Compare mark here with last lesson's.

quiz.py
import gradio as gr

class Question:
    def __init__(self, text, choices, answer):
        self.text = text
        self.choices = choices
        self.answer = answer

    def check(self, guess):
        return guess == self.answer

    def feedback(self, guess):
        if self.check(guess):
            return "Right: " + self.text
        return "Not quite: " + self.text + " The answer is " + self.answer + "."


questions = [
    Question("Which planet is closest to the Sun?", ["Venus", "Mercury", "Mars"], "Mercury"),
    Question("How many legs does a spider have?", ["6", "8", "10"], "8"),
    Question("What is 7 x 8?", ["54", "56", "64"], "56"),
]


def mark(a1, a2, a3):
    answers = [a1, a2, a3]
    score = 0
    lines = ""
    for i in range(len(questions)):
        if questions[i].check(answers[i]):
            score = score + 1
        lines = lines + questions[i].feedback(answers[i]) + "\n"
    return str(score) + " out of " + str(len(questions)), lines


inputs = []
for q in questions:
    inputs.append(gr.Radio(q.choices, label=q.text))

gr.Interface(fn=mark, inputs=inputs, outputs=[gr.Textbox(label="Score"), gr.Textbox(label="Feedback")], title="Quick quiz").launch()
Try it yourselfYour edits are saved in this browser.

InvestigateTrace how each line of code connects to what you see.

Investigate

quiz.py
import gradio as gr

class Question:
    def __init__(self, text, choices, answer):
        self.text = text
        self.choices = choices
        self.answer = answer

    def check(self, guess):
        return guess == self.answer

    def feedback(self, guess):
        if self.check(guess):
            return "Right: " + self.text
        return "Not quite: " + self.text + " The answer is " + self.answer + "."


questions = [
    Question("Which planet is closest to the Sun?", ["Venus", "Mercury", "Mars"], "Mercury"),
    Question("How many legs does a spider have?", ["6", "8", "10"], "8"),
    Question("What is 7 x 8?", ["54", "56", "64"], "56"),
]


def mark(a1, a2, a3):
    answers = [a1, a2, a3]
    score = 0
    lines = ""
    for i in range(len(questions)):
        if questions[i].check(answers[i]):
            score = score + 1
        lines = lines + questions[i].feedback(answers[i]) + "\n"
    return str(score) + " out of " + str(len(questions)), lines


inputs = []
for q in questions:
    inputs.append(gr.Radio(q.choices, label=q.text))

gr.Interface(fn=mark, inputs=inputs, outputs=[gr.Textbox(label="Score"), gr.Textbox(label="Feedback")], title="Quick quiz").launch()

What self is.

Where the rules live now.

A method missing self.

Inside check, what is self.answer for the second question in the list?

Compared with last lesson, what got simpler in mark?

q.check("56") stops with TypeError: Question.check() takes 1 positional argument but 2 were given. Click the line that is wrong.

ModifyChange the code on purpose and check the result.

Modify

Add a hint method (such as the answer's first letter) and use it in the feedback, so a wrong answer gets a hint instead of the answer.

Need a hint?

def hint(self): return "It starts with " + self.answer[0]

Another hint

In feedback, use self.hint() instead of giving the answer away.

Give each question a number of points, and make the score add them up (harder questions worth more).

Need a hint?

Add points to init (self.points = points), give each Question a points value, and add questions[i].points to the score.

Try it yourselfYour edits are saved in this browser.

Add a hint method, and use it in feedback instead of giving the answer.

    Run your program. This ticks when your code does all of the above.

    Give each question its own points, and score by points.

      Run your program. This ticks when your code does all of the above.

      MakeBuild something new using what you have learned. Expect a few tries; that is normal.

      Your quiz with objects

      Rebuild your quiz from last lesson with Question objects, and add something of your own to the class: a hint, points, a topic, or a method that says how hard the question is.

      Try it yourselfYour edits are saved in this browser.

      Build a quiz of at least four Question objects, with the app.

        Run your program. This ticks when your code does all of the above.

        Info

        Where this leads

        Real apps (and Gradio itself) are built from classes: gr.Radio and gr.Textbox are classes, and each component you made is an object.

        You want a second kind of question where the player types the answer. Where does the checking code go?

        For teachers

        An optional lesson. Students rebuild the quiz with a Question class whose objects check answers and give feedback, then add a hint method and points, and rebuild their own quiz with objects. About 45 minutes.

        Open the teacher guide: answers, solutions, slides and a worksheet.

        Students will be able to

        Before class

        Optional: not needed for completing the course. Students who did Objects with turtles have met classes; for others the lesson introduces them briefly. class Question stores each question's text, choices and answer as attributes (self.answer), set in __init__, and has methods check(guess) and feedback(guess). Python passes the object as the first argument of every method, so the first parameter is self (the bug task leaves it out, and the error says it got 2 arguments instead of 1). mark now asks each question to check itself. The info question introduces the idea behind designing with objects: different kinds of question can each have a check method.

        Running the lesson

        1. Predict: draw one Question object as a box with its three values and two methods.
        2. Investigate: ask what self is when questions[2].check(...) runs.
        3. Modify: hint first (a method), then points (an attribute in __init__).

        The hard part (on purpose)

        What self is inside a method. Ask which question check was called on, and what self.answer is for it.

        When students get stuck

        Stretch and support

        Stretch: Make a TypedQuestion class with its own check that compares lower-case text, for questions answered in a Textbox.

        Support: Give students the hint method written out, and ask them only to use it in feedback.

        Where it leads

        Gradio's components are classes too. Machine learning with Gradio (coming later) and games with microStudio build on objects.

        What each step is for

        Now you can
        You reached the endBack to Apps with Gradio