Python
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
424: Building a Flashcard Quiz App
A few years ago, I was helping a junior dev build a study tool for his medical boards. He had the basics down—a list of questions and a list of answers—but he complained that he was "cheating" without realizing it. He wasn't actually learning the material; he was just memorizing the order of the questions. Because the list stayed the same every time he ran the script, his brain just mapped "Question 4" to "Answer 4." This is a classic trap in app development: building a tool that satisfies the technical requirements but fails the actual user experience.
To fix this, we need to move beyond static lists and implement a dynamic system that handles data as objects and randomizes the delivery. In this lesson, we're going to build a Flashcard Quiz App that ensures the user is actually challenged every time they start a session.
Structuring Data with a List of Dictionaries
When you're building something like a quiz, avoid the temptation to keep your questions in one list and your answers in another. It's a nightmare to keep them synced, especially if you decide to delete or move a card. Instead, treat each flashcard as a single entity. I always recommend using a list of dictionaries for this. It keeps the "front" and "back" of the card tied together logically.
flashcards = [
{"question": "What is the time complexity of a Python list append?", "answer": "O(1)"},
{"question": "Which keyword is used to create a function?", "answer": "def"},
{"question": "What does the 'map' function do?", "answer": "Applies a function to all items in an iterable"},
{"question": "What is a lambda function?", "answer": "An anonymous, one-line function"}
]
By structuring it this way, we can pass a single dictionary into a function or loop through it without worrying about index mismatches. It's cleaner, more readable, and much easier to extend if you later decide to add categories or difficulty levels to your cards.
Randomizing the Deck and Running the Game Loop
To solve the "memorizing the order" problem, we'll use the random module. Specifically, random.shuffle(). I've seen developers try to use random.choice() inside a loop, but that's a mistake—you'll end up showing the same card three times and skipping others entirely. Shuffling the list once at the start is the way to go.
Once the deck is shuffled, we can iterate through it using a for loop. We'll capture the user's input and compare it to the "answer" key in our dictionary. Note that I usually add .strip().lower() to both the input and the answer; users are unpredictable with their capitalization and trailing spaces, and failing a card because of a stray space is just frustrating.
import random
def run_quiz(cards):
# Shuffle the list in-place to randomize the order
random.shuffle(cards)
score = 0
for card in cards:
print(f"\nQuestion: {card['question']}")
user_answer = input("Your answer: ").strip().lower()
if user_answer == card['answer'].lower():
print("Correct!")
score += 1
else:
print(f"Wrong. The correct answer was: {card['answer']}")
print(f"\nQuiz complete! Your final score is {score}/{len(cards)}")
run_quiz(flashcards)
The logic here is straightforward, but the power comes from the combination of the data structure and the shuffle. You've turned a static list into a reusable application. If you want to make this more robust, you could move the flashcards into a JSON file, but for the core logic of a quiz app, this pattern is the gold standard.
📋 Practical Task
Implementing a 'Study Again' Pile for Incorrect Answers
Right now, if a user gets a question wrong, the app tells them the answer and moves on. To make this a real learning tool, we need to implement a "Review Pile."
Modify the run_quiz function so that any card the user answers incorrectly is added to a new list called wrong_answers. After the main loop finishes, the program should check if wrong_answers contains any items. If it does, the app should print a message saying "Let's review the ones you missed!" and then loop through the wrong_answers list, presenting those cards to the user one more time until they get them all correct.
There are no comments for now.