# GESP等级：四级 | GESP Python 四级考点
"""
小测：try-except 知识点自测
课程时间：55:00-60:00

共 6 题，每题 10 分，满分 60 分。
运行本文件即可开始测试。
"""

import sys


def run_quiz():
    """运行小测"""

    questions = [
        {
            "question": "⭐ 0. 程序出错有三种类型，下面哪个是'运行时错误'？",
            "options": [
                "A. 代码里少了右括号 → SyntaxError",
                "B. 用户输入了abc但程序要数字 → ValueError",
                "C. 面积公式写成了 π×r×2 而不是 π×r²",
                "D. 把 print 写成了 pint",
            ],
            "answer": "B",
            "explanation": (
                "语法错误（A和D）还没运行就报错了；逻辑错误（C）能跑但结果不对；"
                "运行时错误（B）语法对但执行时报错——try-except 就是用来捕获这种错误的！"
                "【记忆：语法错误说错话🤭 / 运行时半路摔跤🤕 / 逻辑错误结果孬🤔】"
            ),
        },
        {
            "question": "1. try 里面的代码出错了会怎样？",
            "options": [
                "A. 程序立即崩溃退出",
                "B. 跳到对应的 except 块执行，程序继续运行",
                "C. 跳过错误行继续执行下一行",
                "D. 自动重试出错的代码",
            ],
            "answer": "B",
            "explanation": (
                "当 try 块抛出异常时，程序立即停止 try 中剩余代码，"
                "跳转到对应的 except 块。如果 except 处理成功，程序继续运行不会崩溃。"
                "【记忆钩子：try=试一下，except=出错了怎么办】"
            ),
        },
        {
            "question": (
                "2. 以下代码执行后会输出什么？\n\n"
                "   try:\n"
                "       print('A')\n"
                "       int('abc')\n"
                "       print('B')\n"
                "   except ValueError:\n"
                "       print('C')\n"
                "   print('D')"
            ),
            "options": [
                "A. A B C D",
                "B. A C D",
                "C. A C",
                "D. A B D",
            ],
            "answer": "B",
            "explanation": (
                "先输出 A，然后 int('abc') 抛出 ValueError，"
                "立即跳转到 except 块输出 C，最后输出 D。"
                "中间的 print('B') 永远不会执行。"
            ),
        },
        {
            "question": "3. 以下哪个异常是 int('hello') 会触发的？",
            "options": [
                "A. TypeError",
                "B. NameError",
                "C. ValueError",
                "D. ZeroDivisionError",
            ],
            "answer": "C",
            "explanation": (
                "int('hello') 中 'hello' 是字符串，int() 函数无法将其转换为整数，"
                "触发 ValueError。TypeError 是类型错误（如 '1'+2），"
                "NameError 是未定义变量。"
            ),
        },
        {
            "question": (
                "4. 以下代码执行后会输出什么？\n\n"
                "   try:\n"
                "       n = int('10')\n"
                "       result = 10 / n\n"
                "   except ValueError:\n"
                "       print('A')\n"
                "   except ZeroDivisionError:\n"
                "       print('B')\n"
                "   else:\n"
                "       print('C')\n"
                "   finally:\n"
                "       print('D')"
            ),
            "options": [
                "A. A D",
                "B. B D",
                "C. C D",
                "D. D",
            ],
            "answer": "C",
            "explanation": (
                "int('10') 正常转为 10，10 / 10 = 1 正常计算，"
                "没有异常所以跳过 except，执行 else 输出 C，"
                "最后 finally 总是执行输出 D。"
            ),
        },
        {
            "question": "5. 以下哪个场景最适合用 try-except 捕获 ValueError？",
            "options": [
                "A. 文件不存在时读取文件",
                "B. 用户输入 'abc' 但程序期望数字时",
                "C. 网络连接超时时",
                "D. 列表索引超出范围时",
            ],
            "answer": "B",
            "explanation": (
                "ValueError 指值错误——值本身不合法。"
                "用户输入 'abc' 但程序用 int() 转换时抛出 ValueError。"
                "A 是 FileNotFoundError，C 是超时异常，D 是 IndexError。"
            ),
        },
        {
            "question": "6. 使用 try-except 时，以下哪个做法最好？",
            "options": [
                "A. 用 except: 捕获所有异常，简单省事",
                "B. 捕获具体的异常类型（如 ValueError）",
                "C. 在 except 块中不写任何代码",
                "D. 能不用 try-except 就不用",
            ],
            "answer": "B",
            "explanation": (
                "最佳实践是捕获具体的异常类型。"
                "裸 except: 会捕获包括 SystemExit、KeyboardInterrupt 在内的所有异常，"
                "可能掩盖严重问题。"
                "具体捕获让代码更清晰、更安全。"
            ),
        },
    ]

    score = 0
    total = len(questions)

    print("=" * 50)
    print("  try-except 知识点小测")
    print("=" * 50)
    print(f"共 {total} 题，每题 {100 // total} 分\n")

    for i, q in enumerate(questions, 1):
        print(f"\n--- 第 {i} 题 ---")
        print(q["question"])
        print()

        for opt in q["options"]:
            print(f"   {opt}")

        while True:
            user_answer = input("\n你的答案 (输入 A/B/C/D): ").strip().upper()
            if user_answer in ("A", "B", "C", "D"):
                break
            print("请输入 A, B, C 或 D")

        if user_answer == q["answer"]:
            print("✓ 回答正确！")
            score += 100 // total
        else:
            print(f"✗ 回答错误！正确答案是 {q['answer']}")

        print(f"  解析：{q['explanation']}")

    # 输出成绩
    print("\n" + "=" * 50)
    print(f"  得分：{score} / {total * (100 // total)}")
    print("=" * 50)

    percentage = score / (total * (100 // total)) * 100
    if percentage == 100:
        print("评价：满分！你完全掌握了 try-except！")
    elif percentage >= 80:
        print("评价：优秀！大部分知识点都掌握了，复习一下错题。")
    elif percentage >= 60:
        print("评价：及格！建议再回顾一下演示代码。")
    else:
        print("评价：需要加强！建议重新学习知识点部分。")

    print(f"\n记忆钩子：try = 试一下, except = 出错了怎么办")


if __name__ == "__main__":
    run_quiz()
