# 教案：第06节 —— 复合嵌套（下）

---

## 元信息

| 项目 | 内容 |
|------|------|
| **课程编号** | G4_第06节 |
| **GESP等级** | **四级**（GESP Python 四级考点） |
| **适用年龄** | 11-14 岁（编程高手阶段） |
| **核心知识点** | 嵌套结构的增删改、嵌套遍历与筛选、深拷贝与浅拷贝、JSON 序列化 |
| **记忆钩子** | 增删改查四步走 深拷贝是克隆人 浅拷贝是双胞胎 JSON 是通用语言 |
| **身体锚点** | 1. 增（举手加） 2. 删（挥手去） 3. 改（转手腕） 4. 查（手指指） |

---

## 课程目标

1. **掌握** 对嵌套结构进行增、删、改的操作
2. **熟练** 遍历嵌套结构并筛选符合条件的元素
3. **理解** 深拷贝与浅拷贝的区别及其影响
4. **掌握** JSON 序列化与反序列化嵌套数据

---

## 五段式 60 分钟教学流程

---

### 第一段：导入（00:00 - 10:00）—— 回顾 + 引入

#### 教师活动

| 时间 | 活动内容 | 教学方式 |
|------|---------|---------|
| 0-3min | 复习：列表套字典、字典套列表的创建和访问 | 快速问答 |
| 3-6min | 提问：如果要在嵌套结构中插入新数据，该怎么操作？ | 设问引导 |
| 6-10min | 展示今天任务：给嵌套结构做增删改查 + 深拷贝 + JSON | 目标宣布 |

#### 身体锚点

> **【身体锚点 - 增删改查】**
> 增：右手举高做添加动作
> 删：右手挥向左侧做删除动作
> 改：双手转动做修改动作
> 查：食指前伸做指向动作
> 深拷贝：双手模拟克隆人动作

---

### 第二段：知识点精讲（10:00 - 30:00）

#### 2.1 嵌套结构的增删改（7min）

**添加新数据：**

```python
students = [
    {"name": "小明", "score": 95},
    {"name": "小红", "score": 88},
]
students.append({"name": "小刚", "score": 92})
students[0]["age"] = 10
students[0]["rank"] = "A"
```

**修改嵌套数据：**

```python
students[1]["score"] = 92
for student in students:
    if "score" in student:
        student["score"] += 5
updated = [{**s, "score": s["score"] + 5} for s in students if "score" in s]
```

**删除嵌套数据：**

```python
del students[0]["rank"]
removed = students.pop(1)
students = [s for s in students if s["score"] >= 90]
```

#### 2.2 嵌套遍历与筛选（6min）

```python
students = [
    {"name": "小明", "scores": {"py": 95, "math": 92, "eng": 88}},
    {"name": "小红", "scores": {"py": 88, "math": 90, "eng": 85}},
]
for student in students:
    print(f"学生: {student['name']}")
    for subject, score in student["scores"].items():
        print(f"  {subject}: {score}分")

top_py = [s for s in students if s["scores"]["py"] >= 90]

def avg_score(student):
    scores = list(student["scores"].values())
    return sum(scores) / len(scores)

top_students = [s for s in students if avg_score(s) >= 90]
ranked = sorted(students, key=avg_score, reverse=True)
for i, s in enumerate(ranked, 1):
    print(f"第{i}名: {s['name']} 均分{avg_score(s):.1f}")
```

#### 2.3 深拷贝 vs 浅拷贝（4min）

```python
import copy

# 直接赋值 = 共享引用
a = [{"name": "小明", "scores": [95, 92]}]
b = a
b[0]["score"] = 0
print(a[0]["score"])  # 0（被改了！）

# 浅拷贝：外层独立，内层共享
a = [{"name": "小明", "scores": [95, 92]}]
b = copy.copy(a)
b[0]["name"] = "小红"
print(a[0]["name"])    # 小红（被影响了！）

# 深拷贝：完全独立
a = [{"name": "小明", "scores": [95, 92]}]
b = copy.deepcopy(a)
b[0]["name"] = "小红"
b[0]["scores"][0] = 0
print(a[0]["name"])    # 小明（不受影响！）
print(a[0]["scores"])  # [95, 92]（不受影响！）
```

**拷贝类型对比：**

| 操作 | 外层复制 | 内层共享 | 独立程度 |
|------|---------|---------|---------|
| b = a | 不复制 | 完全共享 | 不独立 |
| copy.copy(a) | 复制 | 内层仍共享 | 部分独立 |
| copy.deepcopy(a) | 全部复制 | 全部独立 | 完全独立 |

**记忆钩子：** 浅拷贝 = 双胞胎穿同一件衣服，深拷贝 = 克隆人各有各的衣服

#### 2.4 JSON 序列化（3min）

```python
import json

data = {
    "class": "Python 进阶班",
    "students": [
        {"name": "小明", "scores": [95, 92, 98]},
        {"name": "小红", "scores": [88, 90, 85]},
    ]
}

# Python -> JSON 字符串
json_str = json.dumps(data, ensure_ascii=False, indent=2)
print(json_str)

# JSON 字符串 -> Python
restored = json.loads(json_str)
print(restored["students"][0]["name"])  # 小明

# 保存/读取文件
with open("class_data.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)
with open("class_data.json", "r", encoding="utf-8") as f:
    loaded = json.load(f)
```

---

### 第三段：演示（30:00 - 40:00）

#### 演示 1：学生成绩管理 —— 增删改查

```python
import copy

students = [
    {"name": "小明", "scores": [95, 92, 98]},
    {"name": "小红", "scores": [88, 90, 85]},
]

def add_student(name, scores):
    students.append({"name": name, "scores": scores})
    print(f"已添加学生: {name}")

def update_score(name, idx, new_score):
    for s in students:
        if s["name"] == name:
            s["scores"][idx] = new_score
            return
    print(f"未找到学生: {name}")

def delete_student(name):
    for i, s in enumerate(students):
        if s["name"] == name:
            students.pop(i)
            print(f"已删除学生: {name}")
            return

def backup_data():
    return copy.deepcopy(students)

add_student("小刚", [92, 94, 91])
update_score("小明", 0, 100)
backup = backup_data()
print(f"备份了 {len(backup)} 个学生的数据")
```

#### 演示 2：深拷贝 vs 浅拷贝可视化

```python
import copy

original = [{"items": [1, 2, 3]}, {"items": [4, 5, 6]}]
shallow = copy.copy(original)
shallow[0]["items"].append(999)
print(f"浅拷贝后原始: {original[0]['items']}")  # [1, 2, 3, 999]

original = [{"items": [1, 2, 3]}, {"items": [4, 5, 6]}]
deep = copy.deepcopy(original)
deep[0]["items"].append(999)
print(f"深拷贝后原始: {original[0]['items']}")  # [1, 2, 3]
```

#### 演示 3：嵌套数据导出 JSON

```python
import json
classroom = {
    "name": "Python 班",
    "students": [
        {"name": "小明", "scores": [95, 92]},
    ]
}
print(json.dumps(classroom, ensure_ascii=False, indent=2))


### 第四段：实操练习（40:00 - 55:00）

#### 练习 1：给嵌套结构添加数据（5min）

```
题目：给 students 列表中的每个学生添加一个 grade 字段，值为 A
```

**参考答案：**
```python
students = [
    {"name": "小明", "score": 95},
    {"name": "小红", "score": 88},
]
for s in students:
    s["grade"] = "A"
students = [{**s, "grade": "A"} for s in students]
```

#### 练习 2：嵌套数据筛选（5min）

```
题目：从学生列表中筛选出所有平均分 > 90 的学生
students = [
    {"name": "小明", "scores": [95, 92, 98]},
    {"name": "小红", "scores": [88, 90, 85]},
    {"name": "小刚", "scores": [92, 94, 91]},
]
```

**参考答案：**
```python
top = [s for s in students if sum(s["scores"]) / len(s["scores"]) > 90]
print([s["name"] for s in top])  # ['小明', '小刚']
```

#### 练习 3：深拷贝保护（5min）

```
题目：补全代码，使修改 deep_copy 不影响 original
import copy
original = [{"data": [1, 2, 3]}]
deep_copy = ???
deep_copy[0]["data"].append(4)
print(original[0]["data"])   # 应输出 [1, 2, 3]
print(deep_copy[0]["data"])  # 应输出 [1, 2, 3, 4]
```

**参考答案：**
```python
import copy
original = [{"data": [1, 2, 3]}]
deep_copy = copy.deepcopy(original)
deep_copy[0]["data"].append(4)
print(original[0]["data"])   # [1, 2, 3]
print(deep_copy[0]["data"])  # [1, 2, 3, 4]
```

---

### 第五段：小测（55:00 - 60:00）

#### 题目 1（选择）
以下哪种操作会对原始嵌套数据产生影响？
A. copy.deepcopy()
B. copy.copy()（修改内层）
C. 直接赋值 b = a
D. json 重新加载

**答案：C**（直接赋值是共享引用），B 也会影响内层

#### 题目 2（选择）
深拷贝可以确保什么？
A. 所有层级都独立复制
B. 只复制外层
C. 只复制内层
D. 不复制任何东西

**答案：A**

#### 题目 3（选择）
json.dumps() 的作用是？
A. Python 对象转为 JSON 字符串
B. JSON 字符串转为 Python 对象
C. 文件读写
D. 深拷贝

**答案：A**

#### 题目 4（判断）
浅拷贝后，修改内层列表会影响原始数据。

**答案：** 对（浅拷贝只复制外层，内层仍然共享）

#### 题目 5（填空）
____ 是内置的 JSON 处理模块，____ 用于序列化，____ 用于反序列化。

**答案：** json, json.dumps(), json.loads()

---

## 板书设计

```
+-------------------------------------------------------+
|       第06节 复合嵌套（下）                             |
+-------------------------------------------------------+

  增删改查：
  增：list.append(dict)    dict["key"] = val
  删：del dict["key"]      list.pop(idx)
  改：dict["key"] = val    list[idx] = val
  查：dict["key"]          list[idx]

  拷贝三层次：
  直接赋值  共享引用    不独立
  浅拷贝    内层共享    部分独立
  深拷贝    全部复制    完全独立

  JSON：
  json.dumps()  Python -> JSON
  json.loads()  JSON -> Python

  记忆钩子：
  增删改查四步走 深拷贝是克隆人 浅拷贝是双胞胎
---

## 课后延伸

| 项目 | 内容 |
|------|------|
| 课后练习 | 课后练习_第06节.md |
| 预习内容 | 第06节 函数进阶 |
| 拓展挑战 | 用 JSON 保存和加载完整的班级管理系统 |
| 家长沟通 | 今天学习了嵌套数据的增删改查和深拷贝，孩子能管理复杂数据了 |

---

## 教学反思

| 维度 | 记录 |
|------|------|
| 学生掌握率 | 预计 55% 学生完全理解深拷贝和浅拷贝的区别 |
| 常见困惑 | 深拷贝和浅拷贝的概念比较抽象，需多次演示 |
| 改进方向 | 用内存地址图解方式帮助理解 |
| 备注 | JSON 部分比较简单，大多数学生能快速掌握 |
