# GESP等级：四级 | GESP Python 四级考点
"""
11第5节 · 局部变量 vs 全局变量 + 函数嵌套
=============================================
课程对应：
  - 00:00-10:00 导入：函数里定义的变量外面能用吗？(不能!)
  - 10:00-30:00 知识点：①局部变量 ②全局变量 ③global声明 ④函数嵌套
  - 30:00-40:00 演示：全局size在函数内用→可以但改不了；global size→可以改了
  - 40:00-55:00 实操：①填空局部/全局 ②补全global声明 ③写嵌套函数画复杂图形
  - 55:00-60:00 小测："函数里x=10,外面x是多少?"
  - GESP 考点：#38 函数进阶（变量作用域部分）

运行方式：
  每个函数独立运行，按教学节奏调用。
"""

import turtle
import time


# ============================================================
# 阶段一：导入——函数里定义的变量外面能用吗？（00:00-10:00）
# ============================================================
def demo_intro_scope():
    """
    用"函数内变量vs函数外访问"对比引入。
    老师演示：函数内定义的变量，外面访问会怎样？
    """
    print("=" * 60)
    print(" 导入——函数里定义的变量外面能用吗？")
    print("=" * 60)

    print("\n场景：小明在房间里放了一个玩具，在客厅里能找到吗？")
    print()

    # ========== 第1步：函数内定义变量，函数外访问 ==========
    print("--- 第1步：在函数内定义变量 ---")
    print("  def test():")
    print("      a = 100         # 函数内部定义的变量")
    print("      print(f'函数内：{a}')")
    print()

    # 运行函数
    def test():
        a = 100
        print(f"  函数内 a = {a}")

    test()
    print()

    # ========== 第2步：尝试在函数外访问 ==========
    print("--- 第2步：函数外能访问 a 吗？ ---")
    print("  print(a)   ← 试试看")
    print()

    try:
        print(f"  函数外 a = {a}")
    except NameError as e:
        print(f"  → NameError: {e}")
        print("  结论：函数内定义的变量，外面访问不到！")
    print()

    # ========== 第3步：函数外定义变量 ==========
    print("--- 第3步：反过来——函数外定义，函数内能用吗？ ---")
    print("  b = 200   # 全局变量")
    print()

    b = 200

    def show_b():
        print(f"  函数内 b = {b}")

    show_b()
    print("  结论：函数外定义的变量，函数内可以读取！")
    print()

    # ========== 引出知识点 ==========
    print("🎯 记忆钩子：")
    print("  '局部变量 = 房间里的东西，全局变量 = 客厅里的东西'")
    print("  '房间里定义的东西，只能在房间里用！'")


# ============================================================
# 阶段二：知识点讲解（10:00-30:00）
# ============================================================
def knowledge_local_var():
    """知识点①：局部变量——函数内定义，函数外不能用"""
    print("=" * 60)
    print(" 知识点①：局部变量——函数内定义，函数外不能用")
    print("=" * 60)
    print()

    print("--- 定义 ---")
    print("  在函数内部用 = 赋值的变量 = 局部变量")
    print()

    print("--- 示例 ---")
    print("  def show():")
    print("      message = '你好！'   # message 是局部变量")
    print("      print(message)")
    print()

    def show():
        message = "你好！"
        print(f"   函数内：{message}")

    show()
    print()

    print("--- 尝试在函数外访问 ---")
    try:
        print(f"  函数外：{message}")
    except NameError as e:
        print(f"  → NameError: {e}")
    print()

    print("--- 特征总结 ---")
    print("  ① 函数调用时创建，函数结束后销毁")
    print("  ② 外部无法访问 → NameError")
    print("  ③ 不同函数的局部变量互不干扰")
    print()

    print("--- 不同函数互不干扰的演示 ---")
    print("  def f1(): x = 10")
    print("  def f2(): x = 20")
    print("  f1() 和 f2() 中的 x 互不打架！")
    print()

    def f1():
        x = 10
        print(f"   f1 中的 x = {x}")

    def f2():
        x = 20
        print(f"   f2 中的 x = {x}")

    f1()
    f2()
    print("  结论：每个函数有自己的'房间'，局部变量是房间里的东西")


def knowledge_global_var():
    """知识点②：全局变量——函数外定义，函数内能用"""
    print("=" * 60)
    print(" 知识点②：全局变量——函数外定义，函数内能读取")
    print("=" * 60)
    print()

    # ========== 全局变量定义与读取 ==========
    print("--- 全局变量定义 ---")
    print("  name = '小明'   # 在所有函数之外定义")
    print()

    name = "小明"

    print("--- 函数内读取全局变量 ---")
    print("  def greet():")
    print("      print(f'你好，{name}！')")
    print()

    def greet():
        print(f"  你好，{name}！")

    greet()
    print()

    # ========== 多个函数共享全局变量 ==========
    print("--- 多个函数共享全局变量 ---")
    print("  count = 0")
    print()

    count = 0

    def show_count():
        print(f"  当前 count = {count}")

    def add_one():
        # 注意：这里没有 global，会出问题！
        print(f"  读取 count = {count}")
        # count += 1   ← 如果运行这行会报错！
    print("  读全局：OK ✅")
    print("  改全局：需要 global 声明！")
    print()

    show_count()
    add_one()

    # ========== 重要陷阱演示 ==========
    print()
    print("--- ⚠️ 重要陷阱：函数内直接赋值 = 创建局部变量 ---")
    print()

    size = 10
    print(f"  初始全局 size = {size}")

    def change():
        size = 20      # 这里创建了局部变量 size！
        print(f"  函数内 size = {size}")

    change()
    print(f"  函数外 size = {size}   ← 还是 10！没变！")
    print()
    print("  💡 原因：size = 20 在函数内部创建了新的局部变量")
    print("     并不是修改全局的 size")
    print()
    print("  想修改全局变量？→ 要用 global 声明（见下个知识点）")


def knowledge_global_declaration():
    """知识点③：global 声明——在函数内部修改全局变量"""
    print("=" * 60)
    print(" 知识点③：global 声明——在函数内修改全局变量")
    print("=" * 60)
    print()

    print("--- 语法 ---")
    print("  在函数内部：")
    print("    global 变量名   # 声明：我用的是全局变量")
    print("    变量名 = 新值   # 修改全局变量")
    print()

    # ========== 直接演示 ==========
    print("--- 示例：用 global 修改全局变量 ---")
    print()

    size = 10
    print(f"  初始全局 size = {size}")

    def change():
        global size          # 声明全局
        size = 20             # 修改全局
        print(f"  函数内 size = {size}")

    change()
    print(f"  函数外 size = {size}   ← 变成 20 了！")
    print()

    # ========== 对比演示 ==========
    print("--- 对比：有无 global 的区别 ---")
    print()

    score = 100
    print(f"  初始 score = {score}")
    print()

    def without_global():
        score = 90       # 创建局部变量
        print(f"  without_global 内：{score}")

    def with_global():
        global score     # 声明全局
        score = 90       # 修改全局
        print(f"  with_global 内：{score}")

    without_global()
    print(f"  调用 without_global 后：{score}   ← 没变")
    print()

    with_global()
    print(f"  调用 with_global 后：{score}   ← 变成 90 了！")
    print()

    # ========== 实际应用场景 ==========
    print("--- 实际应用：计数器 ---")
    print()

    counter = 0

    def increment():
        global counter
        counter += 1
        print(f"  第 {counter} 次调用")

    increment()
    increment()
    increment()
    print(f"  最终 counter = {counter}")
    print()

    print("💡 记忆：global 就是'我要用客厅里的那个东西！'")


def knowledge_nested_func():
    """知识点④：函数嵌套——一个函数里面再定义函数"""
    print("=" * 60)
    print(" 知识点④：函数嵌套——一个函数里面再定义函数")
    print("=" * 60)
    print()

    # ========== 基本语法 ==========
    print("--- 基本语法 ---")
    print("  def outer():        # 外层函数")
    print("      print('外层')")
    print()
    print("      def inner():    # 内层函数（在外层内部定义）")
    print("          print('内层')")
    print()
    print("      inner()         # 外层调用内层")
    print()

    def outer():
        print("  外层函数执行了")

        def inner():
            print("  内层函数执行了")

        inner()

    outer()
    print()

    # ========== 内层函数外部不可见 ==========
    print("--- 内层函数外部不可见 ---")
    try:
        inner()   # 尝试在外面调用
    except NameError as e:
        print(f"  outer() 外部调用 inner() → NameError: {e}")
    print()

    # ========== 多个内层函数 ==========
    print("--- 多个内层函数：组织复杂逻辑 ---")
    print()

    def draw_board():
        """模拟：画黑板——把大任务拆成小步骤"""

        def draw_board_bg():
            print("    [内层] 画黑板背景：绿色矩形")

        def draw_chalk_text():
            print("    [内层] 写粉笔字：Hello World")

        def draw_eraser():
            print("    [内层] 画板擦")

        print("  开始画黑板...")
        draw_board_bg()
        draw_chalk_text()
        draw_eraser()
        print("  黑板画完了！")

    draw_board()
    print()

    # ========== 内层访问外层变量 ==========
    print("--- 内层函数可以访问外层函数的局部变量 ---")
    print()

    def outer_with_var():
        msg = "外层消息"

        def inner_access():
            print(f"  内层访问外层变量：{msg}")

        inner_access()

    outer_with_var()
    print()

    print("--- LEGB 变量查找规则 ---")
    print("  Local（当前函数局部）→ Enclosing（外层函数局部）")
    print("  → Global（模块全局）→ Built-in（Python内置）")
    print()

    print("💡 记忆：嵌套函数 = 大房间套小房间")
    print("  小房间能看到大房间的东西（外层变量）")
    print("  但大房间外面看不到小房间的东西（内层函数）")


# ============================================================
# 阶段三：演示——全局变量读取与修改（30:00-40:00）
# ============================================================
def demo_global_read():
    """第1步：全局变量在函数内读取——可以，但改不了"""
    print("=" * 60)
    print(" 演示第1步：函数内读取全局变量——可以")
    print("=" * 60)
    print()

    size = 100

    print(f"  全局 size = {size}")
    print()

    def show_size():
        print(f"  函数内：size = {size}    ← 读取全局变量成功！")

    show_size()
    print()
    print("  ✅ 结论：函数内部可以读取全局变量的值")


def demo_global_try_change():
    """第2步：不改 global 直接赋值——只是创建了局部变量"""
    print("=" * 60)
    print(" 演示第2步：不写 global 直接赋值——局部变量！")
    print("=" * 60)
    print()

    size = 100

    print(f"  初始全局 size = {size}")
    print()

    def try_change():
        size = 50
        print(f"  函数内 size = {size}   ← 以为改了全局，其实创建了局部")

    try_change()
    print(f"  函数外 size = {size}   ← 没有变！还是 100！")
    print()
    print("  ⚠️ 关键理解：size = 50 在函数内创建了新变量")
    print("    这个新变量也叫 size，但它和全局的 size 不是同一个！")
    print("    就像在房间里放了一个新玩具，客厅里原来的还在。")


def demo_global_real_change():
    """第3步：加上 global 声明——才能真正修改全局变量"""
    print("=" * 60)
    print(" 演示第3步：global 声明——真正修改全局变量")
    print("=" * 60)
    print()

    size = 100

    print(f"  初始全局 size = {size}")
    print()

    def real_change():
        global size          # 声明：我用全局的 size
        size = 50            # 修改全局变量
        print(f"  函数内 size = {size}   ← global 声明后修改成功")

    real_change()
    print(f"  函数外 size = {size}   ← 变成 50 了！全局变量被修改了！")
    print()
    print("  ✅ 结论：global 声明 = '我要用客厅里的那个！'")
    print("    有了 global，函数内就能修改全局变量了。")


def demo_global_three_steps():
    """第1-3步连贯演示：全局变量读取→直接赋值陷阱→global 修改"""
    print("=" * 60)
    print(" 完整连贯演示：全局变量的三种情况对比")
    print("=" * 60)
    print()

    size = 100
    print(f"  【初始】全局 size = {size}")
    print()

    # ---------- 情况1：读取 ----------
    print("  【情况1】函数内读取全局变量：")
    print("    def show():")
    print("        print(size)")

    def show():
        print(f"      → size = {size}")    # 读取全局

    show()
    print("    结果：可以读取 ✅")
    print()

    # ---------- 情况2：直接赋值 ----------
    print("  【情况2】函数内直接赋值（无 global）：")
    print("    def try_change():")
    print("        size = 50")

    def try_change():
        size = 50
        print(f"      → 函数内 size = {size}")

    try_change()
    print(f"    函数外 size = {size}   ← 没变！")
    print("    结果：创建了局部变量，全局没改 ⚠️")
    print()

    # ---------- 情况3：global 声明 ----------
    print("  【情况3】函数内 global 声明后赋值：")
    print("    def real_change():")
    print("        global size")
    print("        size = 50")

    def real_change():
        global size
        size = 50
        print(f"      → 函数内 size = {size}")

    real_change()
    print(f"    函数外 size = {size}   ← 变了！")
    print("    结果：全局变量被修改 ✅")
    print()

    # 恢复
    size = 100

    print("  ┌──────────────────────────────────────────────┐")
    print("  │  总结对比表：                                  │")
    print("  │  ① print(size)        → 读全局 ✅             │")
    print("  │  ② size = 新值        → 建局部 ⚠️             │")
    print("  │  ③ global size; size=新值 → 改全局 ✅          │")
    print("  └──────────────────────────────────────────────┘")


def demo_nested_draw():
    """
    演示第4步：函数嵌套——用嵌套函数画复杂图形。
    使用 turtle 画一个小房子，外层函数组织流程，内层函数画各部分。
    """
    print("=" * 60)
    print(" 演示：函数嵌套——用嵌套函数画房子")
    print("=" * 60)
    print()
    print("代码逻辑：")
    print("  外层函数 draw_house() 负责组织整个绘画流程")
    print("  内层函数分别画墙壁、屋顶、窗户")
    print()

    t = turtle.Turtle()
    t.speed(3)
    t.pensize(2)

    # 全局变量：基础尺寸
    size = 80

    def draw_house():
        """外层函数：画房子——组织所有内层函数的调用"""
        global size

        # ---- 内层函数1：画墙壁 ----
        def draw_wall():
            t.color("orange")
            t.begin_fill()
            for _ in range(4):
                t.forward(size)
                t.left(90)
            t.end_fill()

        # ---- 内层函数2：画屋顶 ----
        def draw_roof():
            t.color("brown")
            t.begin_fill()
            t.left(45)
            t.forward(size * 0.7)
            t.right(90)
            t.forward(size * 0.7)
            t.end_fill()
            t.right(45)

        # ---- 内层函数3：画窗户 ----
        def draw_window():
            # 保存位置
            original_pos = t.position()
            original_heading = t.heading()

            # 移动到窗户位置（墙壁中心偏上偏左）
            t.penup()
            t.forward(size * 0.25)
            t.left(90)
            t.forward(size * 0.3)
            t.pendown()

            t.color("lightblue")
            t.begin_fill()
            for _ in range(4):
                t.forward(size * 0.25)
                t.left(90)
            t.end_fill()

            # 画窗框十字
            t.color("white")
            t.pensize(1)
            # 水平线
            t.forward(size * 0.25)
            t.backward(size * 0.125)
            t.left(90)
            t.forward(size * 0.125)
            t.backward(size * 0.25)
            t.forward(size * 0.125)
            t.right(90)
            t.backward(size * 0.125)

            t.pensize(2)
            # 回到原位
            t.penup()
            t.goto(original_pos)
            t.setheading(original_heading)
            t.pendown()

        # ---- 外层函数按顺序调用内层函数 ----
        print("  开始画房子...")
        draw_wall()
        print("  ✅ 墙壁画完了")
        draw_roof()
        print("  ✅ 屋顶画完了")
        t.penup()
        t.forward(size * 0.25)
        t.pendown()
        draw_window()
        print("  ✅ 窗户画完了")
        print("  🏠 房子画好了！")

    draw_house()
    print()

    print("💡 函数嵌套的好处：")
    print("  ① 大任务拆小步骤：画房子 → 画墙壁 + 画屋顶 + 画窗户")
    print("  ② 内层函数只在 draw_house 内有效，不会污染全局命名空间")
    print("  ③ 代码结构清晰：外层组织流程，内层专注细节")

    turtle.done()


# ============================================================
# 阶段四：实操练习（40:00-55:00）
# ============================================================
def practice_answers():
    """实操练习参考答案"""
    print("=" * 60)
    print(" 实操练习参考答案")
    print("=" * 60)
    print()

    # === 练习1：填空——判断局部/全局 ===
    print("--- 练习1：填空——判断局部/全局 ---")
    print()

    name = "小红"     # ① 全局变量

    def say_hello():
        greeting = "你好"   # ② 局部变量
        print(f"  {greeting}，{name}")

    say_hello()
    print()
    print("答案：")
    print("  ① name → 全局变量（在函数外定义）")
    print("  ② greeting → 局部变量（在函数内定义）")
    print("  ③ 函数外能否访问 greeting？→ 不能！NameError")
    print("  ④ 函数内能否访问 name？→ 能！全局变量函数内可读")
    print()

    # === 练习2：补全 global 声明 ===
    print("--- 练习2：补全 global 声明 ---")
    print()

    score = 60

    def add_score():
        global score    # 补全1：global 声明
        score += 10     # 补全2：修改全局变量

    add_score()
    print(f"  第一次调用后 score = {score}")   # 70
    add_score()
    print(f"  第二次调用后 score = {score}")   # 80
    print()

    print("答案：")
    print("""    def add_score():
        global score
        score += 10""")
    print()

    # === 练习3：嵌套函数画复杂图形 ===
    print("--- 练习3：嵌套函数画复杂图形 ---")
    print()

    print("参考代码：")
    print("""
    import turtle
    t = turtle.Turtle()
    t.speed(3)

    def draw_scene():
        '''画场景：太阳 + 地面 + 树'''

        def draw_sun():
            '''画太阳：黄色圆'''
            t.color("yellow")
            t.begin_fill()
            t.circle(30)
            t.end_fill()

        def draw_ground():
            '''画地面：绿色矩形'''
            t.color("green")
            t.begin_fill()
            for _ in range(2):
                t.forward(200)
                t.right(90)
                t.forward(20)
                t.right(90)
            t.end_fill()

        def draw_tree():
            '''画树：棕色树干 + 绿色树冠'''
            # 树干
            t.color("brown")
            t.begin_fill()
            for _ in range(2):
                t.forward(15)
                t.left(90)
                t.forward(40)
                t.left(90)
            t.end_fill()
            # 树冠
            t.color("green")
            t.begin_fill()
            t.circle(25)
            t.end_fill()

        # 按顺序画
        draw_sun()
        t.penup()
        t.goto(-50, -20)
        t.pendown()
        draw_ground()
        t.penup()
        t.goto(50, -20)
        t.pendown()
        draw_tree()

    draw_scene()
    """)

    # 实际运行
    print("运行结果：")
    t = turtle.Turtle()
    t.speed(3)
    t.pensize(2)

    def draw_scene():
        def draw_sun():
            t.color("yellow")
            t.begin_fill()
            t.circle(30)
            t.end_fill()

        def draw_ground():
            t.color("green")
            t.begin_fill()
            t.goto(-80, 0)
            for _ in range(2):
                t.forward(200)
                t.right(90)
                t.forward(15)
                t.right(90)
            t.end_fill()

        def draw_tree():
            # 树干
            t.color("brown")
            t.begin_fill()
            for _ in range(2):
                t.forward(15)
                t.left(90)
                t.forward(40)
                t.left(90)
            t.end_fill()
            # 树冠
            t.penup()
            t.goto(67, 20)
            t.pendown()
            t.color("green")
            t.begin_fill()
            t.circle(22)
            t.end_fill()

        draw_sun()
        draw_ground()
        t.penup()
        t.goto(60, -15)
        t.pendown()
        draw_tree()

    draw_scene()
    print("  ✅ 场景画好了！")
    print()

    print("💡 嵌套函数的好处：")
    print("  ① 每个小功能封装成独立的内层函数")
    print("  ② 外层函数清晰展示整体流程")
    print("  ③ 内层函数不会被外部意外调用")


# ============================================================
# 阶段五：小测（55:00-60:00）
# ============================================================
def demo_quiz():
    """小测题目及正确答案"""
    print("=" * 60)
    print(" 小测：'函数里x=10,外面x是多少?'")
    print("=" * 60)
    print()

    # ---------- 问题1 ----------
    print("--- 问题1：函数内定义 x=10，外面 x 是多少？ ---")
    print()

    print("""  def test():
      x = 10
  test()
  print(x)   # ???
  """)

    print("  A. 10")
    print("  B. None")
    print("  C. 报错 NameError    ← 正确答案")
    print("  D. 不确定")
    print()

    def test():
        x = 10

    test()
    try:
        print(f"  x = {x}")
    except NameError:
        print("  验证：确实报 NameError，因为 x 是局部变量")
    print()

    # ---------- 问题2 ----------
    print("--- 问题2：下面代码输出什么？ ---")
    print()

    a = 5

    def func():
        a = 10

    func()
    print(f"  a = {a}")

    print("""  a = 5
  def func():
      a = 10
  func()
  print(a)
  """)

    print("  A. 5    ← 正确答案")
    print("  B. 10")
    print("  C. 报错")
    print("  D. 15")
    print(f"  实际输出：{a}  ← 函数内 a=10 创建了局部变量，不影响全局")
    print()

    # ---------- 问题3 ----------
    print("--- 问题3：哪段代码能正确修改全局变量？ ---")
    print()

    print("  A.")
    print("""  x = 1
  def change():
      x = 2
  print(x)  # 1  ← 没改！创了局部""")
    print()
    print("  B.")
    print("""  x = 1
  def change():
      global x
      x = 2
  print(x)  # 2  ← 正确答案 ✅""")
    print()
    print("  C. 语法错误：global x = 2 ✗")
    print("  D. print(x) 只是读取，没修改 ✗")
    print()

    # ---------- 问题4 ----------
    print("--- 问题4：函数嵌套说法正确的是？ ---")
    print()
    print("  A. 内层函数可以在任何地方被调用  → 错")
    print("  B. 内层函数只能在外层函数内部被调用  → 正确答案 ✅")
    print("  C. 内层函数不能访问外层函数的变量  → 错（可以访问）")
    print("  D. 嵌套函数最多只能嵌套一层  → 错（可以多层嵌套）")
    print()

    # ---------- 问题5 ----------
    print("--- 问题5：判断对错 ---")
    print()
    print("  局部变量在函数调用结束后仍然存在。")
    print("  答案：错！函数结束后局部变量被销毁。")
    print()

    print("--- 记忆钩子复习 ---")
    print("  '局部变量 = 房间里的东西'")
    print("  '全局变量 = 客厅里的东西'")
    print("  '房间里定义的东西，只能在房间里用'")
    print("  '客厅里的东西，房间里也能看到'")
    print("  '想改客厅的东西？用 global 喊一声！'")


# ============================================================
# 辅助函数：完整演示
# ============================================================
def demo_all_in_one():
    """
    一次性演示所有知识点：
    局部变量 → 全局变量读取 → global 修改 → 函数嵌套
    """
    print("=" * 60)
    print(" 完整演示：局部变量 vs 全局变量 + 函数嵌套")
    print("=" * 60)
    print()

    # 1. 全局变量
    print("1. 定义一个全局变量：")
    message = "全局消息"
    print(f"   message = '{message}'")
    print()

    # 2. 函数中使用全局变量
    print("2. 函数内读取全局变量：")

    def show_global():
        print(f"   函数内读取：{message}")

    show_global()
    print()

    # 3. 局部变量
    print("3. 函数内定义局部变量：")

    def show_local():
        local_msg = "局部消息"
        print(f"   函数内：{local_msg}")

    show_local()
    try:
        print(f"   函数外：{local_msg}")
    except NameError:
        print("   函数外访问局部变量 → NameError")
    print()

    # 4. global 修改
    print("4. 用 global 修改全局变量：")

    counter = 0

    def increment():
        global counter
        counter += 1
        print(f"   第 {counter} 次调用")

    increment()
    increment()
    increment()
    print(f"   最终 counter = {counter}")
    print()

    # 5. 函数嵌套
    print("5. 函数嵌套——大任务拆小步骤：")

    def manage_task():
        print("   [外层] 开始执行任务")

        def step1():
            print("   [内层] 步骤1：准备数据")

        def step2():
            print("   [内层] 步骤2：处理数据")

        def step3():
            print("   [内层] 步骤3：输出结果")

        step1()
        step2()
        step3()
        print("   [外层] 任务执行完毕")

    manage_task()


# ============================================================
# 入口
# ============================================================
if __name__ == "__main__":
    print(" 11第5节 · 局部变量 vs 全局变量 + 函数嵌套")
    print(" GESP #38")
    print("=" * 60)
    print()
    print("请选择要运行的功能：")
    print("  1  - 导入：函数内变量外面能用吗？（00:00-10:00）")
    print("  2  - 知识点①：局部变量——函数内定义，外面不能用")
    print("  3  - 知识点②：全局变量——函数外定义，函数内能读")
    print("  4  - 知识点③：global 声明——函数内修改全局变量")
    print("  5  - 知识点④：函数嵌套——函数里再定义函数")
    print("  6  - 演示①：函数内读取全局变量（30:00-40:00）")
    print("  7  - 演示②：直接赋值的陷阱——局部变量！")
    print("  8  - 演示③：global 声明——真修改了！")
    print("  9  - 演示三连：读取→陷阱→global 对比")
    print("  10 - 演示④：嵌套函数画房子")
    print("  11 - 实操练习参考答案（40:00-55:00）")
    print("  12 - 小测答案（55:00-60:00）")
    print("  13 - 完整演示：全部知识点一览")
    print()

    try:
        choice = int(input("请输入数字 (1-13)，直接回车默认 9: ") or "9")
    except (ValueError, EOFError):
        choice = 9

    print()

    functions = {
        1: demo_intro_scope,
        2: knowledge_local_var,
        3: knowledge_global_var,
        4: knowledge_global_declaration,
        5: knowledge_nested_func,
        6: demo_global_read,
        7: demo_global_try_change,
        8: demo_global_real_change,
        9: demo_global_three_steps,
        10: demo_nested_draw,
        11: practice_answers,
        12: demo_quiz,
        13: demo_all_in_one,
    }

    func = functions.get(choice)
    if func:
        func()
    else:
        print("无效选择，运行三连对比演示")
        demo_global_three_steps()

# ===== 补充：浅拷贝陷阱（GESP四级真题考点）=====
print("\n" + "="*50)
print("浅拷贝陷阱")
print("="*50)
a = [1, 2, [3, 4]]
b = a[:]  # 浅拷贝
b[0] = 10
b[2][0] = 30
print(f"a = {a}")  # 内层被改了！
print(f"b = {b}")
print("原因：[:]只拷贝外层，内层列表还是共用的")

import copy
c = copy.deepcopy(a)
c[2][0] = 99
print(f"深拷贝后 a = {a}")  # 没受影响
print(f"深拷贝后 c = {c}")

# nonlocal演示
print("\n" + "="*50)
print("nonlocal关键字")
print("="*50)
def outer():
    x = 10
    def inner():
        nonlocal x
        x = 20
    inner()
    print(f"outer里的x被inner改了: x = {x}")
outer()
