Глава 12 · Множество увлекательных мини-проектов!

Проект: викторина

Самый важный архитектурный урок главы: вопросы — это данные, а не код, и алгоритм не должен меняться, когда меняются данные.

Используем
listdictforinputifсчётчик
Уровень
★★★★ challenge
Результат
текстовая викторина

Что создаём

Викторину из нескольких вопросов: программа задаёт вопрос, принимает ответ, сравнивает его с правильным, считает счёт и в конце показывает результат.

Вопрос 1: Столица Франции?
Ваш ответ: paris
 Верно!
Вопрос 2: 7 * 8?
Ваш ответ: 54
 Неверно. Правильный ответ: 56
Счёт: 1 из 2
Детерминированный пример выполнения

Данные vs алгоритм — главный урок этого проекта

Есть соблазн написать викторину так:

Три вопроса: захардкоженная логика → данные + цикл
Вопросы «зашиты» в код
question1 = "Столица Франции?"
answer1 = "paris"
user1 = input(question1 + " ").strip().lower()
if user1 == answer1:
    score += 1

question2 = "7 * 8?"
answer2 = "56"
user2 = input(question2 + " ").strip().lower()
if user2 == answer2:
    score += 1

# ...и так для каждого следующего вопроса
Вопросы — данные, алгоритм один
questions = [
    {"question": "Столица Франции?", "answer": "paris"},
    {"question": "7 * 8?", "answer": "56"},
]

score = 0
for q in questions:
    user_answer = input(q["question"] + " ").strip().lower()
    if user_answer == q["answer"]:
        score += 1
Что использовать сегодня: хранить вопросы как ДАННЫЕ (список словарей), а не как повторяющийся код. Если вопросов станет 20 вместо 2, левый вариант пришлось бы переписывать заново, а правый — просто дополнить список. Алгоритм не меняется, когда меняются данные — в этом суть data-driven programming.
Рефакторинг
Переход от левого варианта к правому называется рефакторингом — мы улучшаем внутреннюю структуру программы, не меняя то, что она должна делать. Программа с двумя вопросами ведёт себя одинаково в обеих версиях — правая просто лучше устроена и легче расширяется.

Алгоритм

СТАРТПолучить следующийэлемент из questionsquestionДАспросить, сравнить,посчитатьназадНЕТКОНЕЦ
for question in questions — один и тот же алгоритм для любого числа вопросов
показатьquestion['question']user_answer =input()нормализовать:.strip().lower()user_answer ==question['answer']?ДАscore += 1НЕТпоказать правильныйответ
Одна итерация цикла — этот блок повторяется for-циклом сверху, для каждого вопроса

Финальный код

viktorina.py
questions = [
    {"question": "Столица Франции?", "answer": "paris"},
    {"question": "7 * 8?", "answer": "56"},
    {"question": "Язык, который мы изучаем?", "answer": "python"},
]

score = 0
for q in questions:
    user_answer = input(q["question"] + " ").strip().lower()
    if user_answer == q["answer"]:
        print("✅ Верно!")
        score += 1
    else:
        print(f"❌ Неверно. Правильный ответ: {q['answer']}")

print(f"Счёт: {score} из {len(questions)}")

Уровень 4: процент правильных ответов

viktorina_procent.py
procent = score / len(questions) * 100
print(f"Результат: {procent:.0f}%")

Debug Lab

Что произойдёт, если убрать .strip().lower() при нормализации ответа?

«Paris» и «paris» — разные строки
Без нормализации регистр и лишние пробелы делают правильный ответ «неверным» — та же чувствительность строк к регистру и пробелам, что и в главе 8. Всегда нормализуйте пользовательский ввод перед сравнением.
Практика: викторина из списка вопросов
Интерактивный ноутбук прямо в браузере — Python 3.14 через Pyodide, без установки
Открыть практику →
Практика (★★★★): процент правильных ответов
Интерактивный ноутбук прямо в браузере — Python 3.14 через Pyodide, без установки
Открыть практику →