Series Article

Day02_Python数据结构与文件操作

今天我们要完成的目标:深入学习Python的数据结构、掌握文件读写操作、理解异常处理机制、能够处理JSON和CSV格式的数据。

今天结束后你应该能做到:

  • 熟练使用列表、字典、集合、元组
  • 掌握列表推导式和字典推导式
  • 能够读写文本文件、JSON文件、CSV文件
  • 理解并使用异常处理
  • 掌握上下文管理器(with语句)
  • 完成一个数据处理小项目

列表的深入使用

列表基础回顾

列表是Python中最常用的数据结构,可以存储多个元素。

# 创建列表
fruits = ["苹果", "香蕉", "橙子"]
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True]

# 访问元素
print(fruits[0])   # 苹果
print(fruits[-1])  # 橙子(最后一个)

# 列表长度
print(len(fruits))  # 3

列表的常用操作

# 添加元素
fruits = ["苹果", "香蕉"]
fruits.append("橙子")        # 末尾添加
print(fruits)  # ['苹果', '香蕉', '橙子']

fruits.insert(1, "葡萄")     # 指定位置插入
print(fruits)  # ['苹果', '葡萄', '香蕉', '橙子']

# 删除元素
fruits.remove("香蕉")        # 删除指定元素
print(fruits)  # ['苹果', '葡萄', '橙子']

last = fruits.pop()          # 删除并返回最后一个
print(last)    # 橙子
print(fruits)  # ['苹果', '葡萄']

# 修改元素
fruits[0] = "西瓜"
print(fruits)  # ['西瓜', '葡萄']

列表切片

切片是Python的一个强大特性,可以快速获取列表的一部分。

numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 基本切片 [start:end](不包含end)
print(numbers[2:5])    # [2, 3, 4]
print(numbers[:3])     # [0, 1, 2](从开头到索引3)
print(numbers[7:])     # [7, 8, 9](从索引7到结尾)

# 步长切片 [start:end:step]
print(numbers[::2])    # [0, 2, 4, 6, 8](每隔一个取一个)
print(numbers[1::2])   # [1, 3, 5, 7, 9]
print(numbers[::-1])   # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0](反转)

列表的其他方法

numbers = [3, 1, 4, 1, 5, 9, 2, 6]

# 排序
numbers.sort()              # 原地排序
print(numbers)  # [1, 1, 2, 3, 4, 5, 6, 9]

numbers.sort(reverse=True)  # 降序排序
print(numbers)  # [9, 6, 5, 4, 3, 2, 1, 1]

# 不改变原列表的排序
original = [3, 1, 4, 1, 5]
sorted_list = sorted(original)
print(original)     # [3, 1, 4, 1, 5]
print(sorted_list)  # [1, 1, 3, 4, 5]

# 反转
numbers.reverse()
print(numbers)  # [1, 1, 2, 3, 4, 5, 6, 9]

# 统计和查找
print(numbers.count(1))   # 2(元素1出现的次数)
print(numbers.index(5))   # 5(元素5的索引位置)

练习1:列表操作实战

我先写一个学生成绩管理的例子:

# student_scores.py
scores = [85, 92, 78, 90, 88]

print(f"总分:{sum(scores)}")
print(f"平均分:{sum(scores) / len(scores):.2f}")
print(f"最高分:{max(scores)}")
print(f"最低分:{min(scores)}")

# 排序后显示
sorted_scores = sorted(scores, reverse=True)
print(f"成绩排名:{sorted_scores}")

现在你来练习:

  1. 购物车管理:创建shopping_cart.py

    • 创建一个空列表cart
    • 添加5个商品(字符串)
    • 删除第3个商品
    • 在第2个位置插入一个新商品
    • 打印最终的购物车
  2. 数字处理:创建number_processor.py

    • 创建列表:[10, 25, 3, 47, 15, 8, 33, 21]
    • 找出所有大于20的数字
    • 计算所有偶数的和
    • 将列表反转并打印
  3. 成绩分析:创建grade_analysis.py

    • 创建10个学生的成绩列表(随意填写)
    • 计算平均分
    • 找出高于平均分的成绩
    • 统计及格人数(>=60)

列表推导式

列表推导式是Python的一个优雅特性,可以用一行代码创建列表。

基本语法

# 传统方式
squares = []
for i in range(1, 6):
    squares.append(i ** 2)
print(squares)  # [1, 4, 9, 16, 25]

# 列表推导式
squares = [i ** 2 for i in range(1, 6)]
print(squares)  # [1, 4, 9, 16, 25]

带条件的列表推导式

# 筛选偶数
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = [n for n in numbers if n % 2 == 0]
print(evens)  # [2, 4, 6, 8, 10]

# 筛选偶数
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = [n for n in numbers if n % 2 == 0]
print(evens)  # [2, 4, 6, 8, 10]

# 字符串处理
words = ["hello", "world", "python", "code"]
upper_words = [word.upper() for word in words]
print(upper_words)  # ['HELLO', 'WORLD', 'PYTHON', 'CODE']

# 带if-else的推导式
numbers = [1, 2, 3, 4, 5]
result = ["偶数" if n % 2 == 0 else "奇数" for n in numbers]
print(result)  # ['奇数', '偶数', '奇数', '偶数', '奇数']

嵌套列表推导式

# 创建二维列表
matrix = [[i * j for j in range(1, 4)] for i in range(1, 4)]
print(matrix)
# [[1, 2, 3],
#  [2, 4, 6],
#  [3, 6, 9]]

# 展平二维列表
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [num for row in matrix for num in row]
print(flat)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

练习2:列表推导式实战

我先写一个温度转换的例子:

# temperature_converter.py
celsius_temps = [0, 10, 20, 30, 40]
fahrenheit_temps = [c * 9/5 + 32 for c in celsius_temps]

for c, f in zip(celsius_temps, fahrenheit_temps):
    print(f"{c}°C = {f}°F")

现在你来练习:

  1. 数字筛选:创建number_filter.py

    • 创建1-50的列表
    • 筛选出所有能被3整除的数
    • 筛选出所有个位数是5的数
  2. 字符串处理:创建string_processor.py

    • 创建列表:["apple", "banana", "cherry", "date"]
    • 获取所有字符串的长度列表
    • 筛选出长度大于5的字符串
  3. 成绩等级:创建grade_level.py

    • 创建成绩列表:[85, 92, 78, 90, 65, 88, 76, 95, 70, 82]
    • 用列表推导式转换为等级(>=90优秀,>=80良好,>=60及格,<60不及格)

字典的深入使用

字典基础

字典是键值对的集合,类似于现实中的字典,通过”词”(键)查找”释义”(值)。

# 创建字典
student = {
    "name": "张三",
    "age": 20,
    "major": "计算机科学"
}

# 访问值
print(student["name"])      # 张三
print(student.get("age"))   # 20

# get方法的优势:键不存在时不会报错
print(student.get("grade", "未录入"))  # 未录入(默认值)

字典的常用操作

# 添加/修改
student = {"name": "张三", "age": 20}
student["major"] = "计算机"     # 添加新键值对
student["age"] = 21             # 修改已有键的值
print(student)  # {'name': '张三', 'age': 21, 'major': '计算机'}

# 删除
del student["age"]              # 删除指定键
print(student)  # {'name': '张三', 'major': '计算机'}

age = student.pop("major")      # 删除并返回值
print(age)      # 计算机

# 检查键是否存在
if "name" in student:
    print("姓名存在")

# 获取所有键、值、键值对
person = {"name": "李四", "age": 25, "city": "北京"}
print(person.keys())    # dict_keys(['name', 'age', 'city'])
print(person.values())  # dict_values(['李四', 25, '北京'])
print(person.items())   # dict_items([('name', '李四'), ('age', 25), ('city', '北京')])

遍历字典

student = {"name": "张三", "age": 20, "major": "计算机"}

# 遍历键
for key in student:
    print(key)

# 遍历键值对
for key, value in student.items():
    print(f"{key}: {value}")

# 输出:
# name: 张三
# age: 20
# major: 计算机

字典推导式

# 创建字典
squares = {x: x**2 for x in range(1, 6)}
print(squares)  # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# 筛选字典
prices = {"apple": 5, "banana": 3, "orange": 6, "grape": 8}
expensive = {k: v for k, v in prices.items() if v > 5}
print(expensive)  # {'orange': 6, 'grape': 8}

# 转换字典
original = {"a": 1, "b": 2, "c": 3}
doubled = {k: v * 2 for k, v in original.items()}
print(doubled)  # {'a': 2, 'b': 4, 'c': 6}

练习3:字典操作实战

我先写一个学生信息管理的例子:

# student_info.py
students = {
    "S001": {"name": "张三", "age": 20, "score": 85},
    "S002": {"name": "李四", "age": 21, "score": 92},
    "S003": {"name": "王五", "age": 19, "score": 78}
}

# 打印所有学生信息
for student_id, info in students.items():
    print(f"学号:{student_id}")
    print(f"姓名:{info['name']}, 年龄:{info['age']}, 成绩:{info['score']}")
    print("-" * 30)

# 计算平均分
total_score = sum(info["score"] for info in students.values())
avg_score = total_score / len(students)
print(f"平均分:{avg_score:.2f}")

现在你来练习:

  1. 商品库存管理:创建inventory.py

    • 创建字典存储5个商品的库存(商品名:数量)
    • 添加2个新商品
    • 更新某个商品的库存
    • 删除一个商品
    • 打印所有库存信息
  2. 单词计数:创建word_counter.py

    • 给定句子:"python is great and python is easy"
    • 统计每个单词出现的次数(用字典存储)
    • 打印结果
  3. 成绩统计:创建score_stats.py

    • 创建字典:{"语文": 85, "数学": 92, "英语": 78, "物理": 88, "化学": 90}
    • 计算总分和平均分
    • 找出最高分的科目
    • 找出所有分数大于85的科目

集合和元组

集合(Set)

集合是无序且不重复的元素集合,主要用于去重和集合运算。

# 创建集合
fruits = {"苹果", "香蕉", "橙子"}
numbers = {1, 2, 3, 4, 5}

# 从列表创建集合(自动去重)
numbers_list = [1, 2, 2, 3, 3, 3, 4, 5]
unique_numbers = set(numbers_list)
print(unique_numbers)  # {1, 2, 3, 4, 5}

# 添加和删除
fruits.add("葡萄")
fruits.remove("香蕉")
print(fruits)  # {'苹果', '橙子', '葡萄'}

# 集合运算
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}

print(set1 | set2)  # 并集:{1, 2, 3, 4, 5, 6, 7, 8}
print(set1 & set2)  # 交集:{4, 5}
print(set1 - set2)  # 差集:{1, 2, 3}
print(set1 ^ set2)  # 对称差:{1, 2, 3, 6, 7, 8}

元组(Tuple)

元组类似列表,但是不可修改,通常用于存储不应该改变的数据。

# 创建元组
point = (3, 4)
person = ("张三", 20, "北京")

# 访问元素
print(point[0])    # 3
print(person[1])   # 20

# 元组解包
x, y = point
name, age, city = person
print(f"{name}今年{age}岁,住在{city}")

# 单元素元组(注意逗号)
single = (5,)      # 这是元组
not_tuple = (5)    # 这只是整数5

# 元组的不可变性
# point[0] = 5     # 这会报错!

练习4:集合和元组实战

我先写一个例子:

# data_analysis.py
# 去重统计
visitors_day1 = ["张三", "李四", "王五", "张三", "赵六"]
visitors_day2 = ["李四", "王五", "孙七", "周八"]

unique_day1 = set(visitors_day1)
unique_day2 = set(visitors_day2)

print(f"第一天访客:{len(unique_day1)}人")
print(f"第二天访客:{len(unique_day2)}人")
print(f"两天都来的:{unique_day1 & unique_day2}")
print(f"只在第一天来的:{unique_day1 - unique_day2}")

现在你来练习:

  1. 标签去重:创建tag_processor.py

    • 创建两个文章的标签列表(有重复)
    • 去重后统计每篇文章有多少个标签
    • 找出两篇文章的共同标签
  2. 坐标处理:创建coordinate.py

    • 创建5个坐标点(用元组表示)
    • 计算每个点到原点的距离
    • 找出距离原点最近的点
  3. 学生选课:创建course_selection.py

    • 创建3个学生选的课程集合
    • 找出所有学生都选的课程
    • 找出至少有一个学生选的所有课程

文件操作基础

读取文本文件

文件操作是编程中非常重要的技能,让我们从最基础的文本文件开始。

# 读取整个文件
with open("example.txt", "r", encoding="utf-8") as file:
    content = file.read()
    print(content)

# 按行读取
with open("example.txt", "r", encoding="utf-8") as file:
    lines = file.readlines()
    for line in lines:
        print(line.strip())  # strip()去除换行符

# 逐行读取(推荐,内存友好)
with open("example.txt", "r", encoding="utf-8") as file:
    for line in file:
        print(line.strip())

写入文本文件

# 写入文件(覆盖模式)
with open("output.txt", "w", encoding="utf-8") as file:
    file.write("第一行\n")
    file.write("第二行\n")

# 追加模式
with open("output.txt", "a", encoding="utf-8") as file:
    file.write("追加的内容\n")

# 写入多行
lines = ["第一行", "第二行", "第三行"]
with open("output.txt", "w", encoding="utf-8") as file:
    file.write("\n".join(lines))

为什么使用with语句?

with语句是上下文管理器,它会自动帮你关闭文件,即使出现错误也能正确关闭。

# 不推荐的方式
file = open("example.txt", "r")
content = file.read()
file.close()  # 容易忘记关闭

# 推荐的方式
with open("example.txt", "r") as file:
    content = file.read()
# 文件自动关闭

练习5:文本文件操作

我先写一个日志记录的例子:

# log_writer.py
import datetime

def write_log(message):
    """写入日志"""
    timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    log_entry = f"[{timestamp}] {message}\n"
    
    with open("app.log", "a", encoding="utf-8") as file:
        file.write(log_entry)

# 测试
write_log("程序启动")
write_log("用户登录成功")
write_log("数据保存完成")

# 读取日志
print("日志内容:")
with open("app.log", "r", encoding="utf-8") as file:
    print(file.read())

现在你来练习:

  1. 待办事项:创建todo_file.py

    • 创建一个待办事项列表(列表)
    • 将所有待办事项写入todo.txt文件
    • 读取文件并打印所有待办事项
  2. 成绩记录:创建score_file.py

    • 创建学生成绩字典:{"张三": 85, "李四": 92, "王五": 78}
    • 将成绩写入scores.txt,格式:姓名: 分数
    • 读取文件并计算平均分
  3. 文本统计:创建text_stats.py

    • 创建一个包含多行文本的文件
    • 读取文件并统计:总行数、总字数、总字符数
    • 打印统计结果

JSON文件操作

JSON是一种轻量级的数据交换格式,在Web开发和API中非常常用。

什么是JSON?

JSON(JavaScript Object Notation)看起来很像Python的字典和列表。

{
    "name": "张三",
    "age": 20,
    "courses": ["Python", "Java", "数据库"],
    "scores": {
        "Python": 95,
        "Java": 88
    }
}

写入JSON文件

import json

# Python数据
student = {
    "name": "张三",
    "age": 20,
    "major": "计算机科学",
    "courses": ["Python", "Java", "数据库"],
    "scores": {"Python": 95, "Java": 88}
}

# 写入JSON文件
with open("student.json", "w", encoding="utf-8") as file:
    json.dump(student, file, ensure_ascii=False, indent=2)

# ensure_ascii=False:支持中文
# indent=2:格式化输出,缩进2个空格

读取JSON文件

import json

# 读取JSON文件
with open("student.json", "r", encoding="utf-8") as file:
    student = json.load(file)

print(student["name"])      # 张三
print(student["courses"])   # ['Python', 'Java', '数据库']

JSON字符串转换

import json

# Python对象转JSON字符串
data = {"name": "李四", "age": 25}
json_str = json.dumps(data, ensure_ascii=False)
print(json_str)  # {"name": "李四", "age": 25}

# JSON字符串转Python对象
json_str = '{"name": "王五", "age": 30}'
data = json.loads(json_str)
print(data["name"])  # 王五

练习6:JSON文件操作

我先写一个配置文件管理的例子:

# config_manager.py
import json

# 创建配置
config = {
    "app_name": "我的应用",
    "version": "1.0.0",
    "database": {
        "host": "localhost",
        "port": 3306,
        "name": "mydb"
    },
    "features": ["登录", "注册", "数据分析"]
}

# 保存配置
with open("config.json", "w", encoding="utf-8") as file:
    json.dump(config, file, ensure_ascii=False, indent=2)

# 读取配置
with open("config.json", "r", encoding="utf-8") as file:
    loaded_config = json.load(file)

print(f"应用名称:{loaded_config['app_name']}")
print(f"数据库地址:{loaded_config['database']['host']}")
print(f"功能列表:{', '.join(loaded_config['features'])}")

现在你来练习:

  1. 学生数据库:创建student_db.py

    • 创建3个学生的信息(字典列表)
    • 保存到students.json
    • 读取并打印所有学生信息
    • 计算所有学生的平均年龄
  2. 购物车保存:创建cart_storage.py

    • 创建购物车数据(商品列表,每个商品包含名称、价格、数量)
    • 保存到cart.json
    • 读取并计算总价
  3. 用户设置:创建user_settings.py

    • 创建用户设置字典(主题、语言、通知开关等)
    • 保存到settings.json
    • 读取并修改某个设置
    • 再次保存

CSV文件操作

CSV(Comma-Separated Values)是一种常见的表格数据格式,Excel可以直接打开。

写入CSV文件

import csv

# 写入CSV
students = [
    ["姓名", "年龄", "成绩"],
    ["张三", 20, 85],
    ["李四", 21, 92],
    ["王五", 19, 78]
]

with open("students.csv", "w", newline="", encoding="utf-8") as file:
    writer = csv.writer(file)
    writer.writerows(students)

# 使用字典写入
students_dict = [
    {"姓名": "张三", "年龄": 20, "成绩": 85},
    {"姓名": "李四", "年龄": 21, "成绩": 92},
    {"姓名": "王五", "年龄": 19, "成绩": 78}
]

with open("students_dict.csv", "w", newline="", encoding="utf-8") as file:
    fieldnames = ["姓名", "年龄", "成绩"]
    writer = csv.DictWriter(file, fieldnames=fieldnames)
    
    writer.writeheader()  # 写入表头
    writer.writerows(students_dict)

读取CSV文件

import csv

# 读取CSV
with open("students.csv", "r", encoding="utf-8") as file:
    reader = csv.reader(file)
    for row in reader:
        print(row)

# 使用字典读取
with open("students_dict.csv", "r", encoding="utf-8") as file:
    reader = csv.DictReader(file)
    for row in reader:
        print(f"{row['姓名']}: {row['成绩']}分")

练习7:CSV文件操作

我先写一个销售数据分析的例子:

# sales_analysis.py
import csv

# 创建销售数据
sales = [
    ["日期", "商品", "数量", "单价"],
    ["2024-01-01", "苹果", 10, 5.5],
    ["2024-01-01", "香蕉", 15, 3.0],
    ["2024-01-02", "苹果", 8, 5.5],
    ["2024-01-02", "橙子", 12, 4.0]
]

# 写入CSV
with open("sales.csv", "w", newline="", encoding="utf-8") as file:
    writer = csv.writer(file)
    writer.writerows(sales)

# 读取并分析
total_revenue = 0
with open("sales.csv", "r", encoding="utf-8") as file:
    reader = csv.reader(file)
    next(reader)  # 跳过表头
    
    for row in reader:
        quantity = int(row[2])
        price = float(row[3])
        revenue = quantity * price
        total_revenue += revenue
        print(f"{row[0]} - {row[1]}: {revenue}元")

print(f"\n总收入:{total_revenue}元")

现在你来练习:

  1. 员工信息表:创建employee_data.py

    • 创建5个员工的信息(姓名、部门、工资)
    • 写入employees.csv
    • 读取并计算平均工资
    • 找出工资最高的员工
  2. 考试成绩表:创建exam_scores.py

    • 创建学生成绩表(姓名、语文、数学、英语)
    • 写入scores.csv
    • 读取并计算每个学生的总分
    • 按总分排序并输出
  3. 产品库存表:创建inventory_csv.py

    • 创建产品库存(产品名、数量、价格)
    • 写入inventory.csv
    • 读取并计算库存总价值
    • 找出库存不足10的产品

异常处理

什么是异常?

异常就是程序运行时出现的错误。如果不处理,程序会直接崩溃。

# 这会导致程序崩溃
# number = int("abc")  # ValueError: invalid literal for int()

# 这也会崩溃
# result = 10 / 0  # ZeroDivisionError: division by zero

try-except基本用法

# 基本异常处理
try:
    number = int(input("请输入一个数字:"))
    result = 10 / number
    print(f"结果:{result}")
except ValueError:
    print("输入的不是有效数字!")
except ZeroDivisionError:
    print("不能除以零!")

捕获多个异常

# 方式1:分别处理
try:
    # 可能出错的代码
    pass
except ValueError:
    print("值错误")
except TypeError:
    print("类型错误")

# 方式2:统一处理
try:
    # 可能出错的代码
    pass
except (ValueError, TypeError):
    print("输入错误")

# 方式3:捕获所有异常
try:
    # 可能出错的代码
    pass
except Exception as e:
    print(f"发生错误:{e}")

try-except-else-finally

try:
    file = open("data.txt", "r")
    content = file.read()
except FileNotFoundError:
    print("文件不存在")
else:
    # 没有异常时执行
    print("文件读取成功")
finally:
    # 无论是否异常都执行
    print("操作完成")

实际应用场景

def safe_divide(a, b):
    """安全的除法运算"""
    try:
        result = a / b
        return result
    except ZeroDivisionError:
        print("错误:除数不能为零")
        return None
    except TypeError:
        print("错误:参数必须是数字")
        return None

# 测试
print(safe_divide(10, 2))    # 5.0
print(safe_divide(10, 0))    # None
print(safe_divide(10, "a"))  # None

练习8:异常处理实战

我先写一个安全的用户输入处理:

# safe_input.py
def get_integer(prompt):
    """获取整数输入,带异常处理"""
    while True:
        try:
            value = int(input(prompt))
            return value
        except ValueError:
            print("请输入有效的整数!")

def get_positive_number(prompt):
    """获取正数"""
    while True:
        try:
            value = float(input(prompt))
            if value <= 0:
                print("请输入正数!")
                continue
            return value
        except ValueError:
            print("请输入有效的数字!")

# 测试(用变量模拟)
def test_safe_input():
    # 模拟输入
    test_inputs = ["abc", "123", "-5", "45.5"]
    
    for test_input in test_inputs:
        try:
            result = int(test_input)
            print(f"输入 '{test_input}' -> 成功:{result}")
        except ValueError:
            print(f"输入 '{test_input}' -> 失败:不是有效整数")

test_safe_input()

现在你来练习:

  1. 文件读取器:创建safe_file_reader.py

    • 定义函数读取文件内容
    • 处理文件不存在的异常
    • 处理编码错误的异常
    • 测试读取存在和不存在的文件
  2. 计算器:创建safe_calculator.py

    • 定义函数进行四则运算
    • 处理除零异常
    • 处理类型错误
    • 测试各种情况
  3. 数据转换器:创建data_converter.py

    • 定义函数将字符串列表转换为整数列表
    • 处理转换失败的情况
    • 返回成功转换的数字和失败的项
    • 测试:["1", "2", "abc", "4", "xyz"]

综合实战:学生成绩管理系统

现在我们把今天学到的所有知识整合起来,做一个完整的项目。

最终项目:学生成绩管理系统

我先给你演示完整代码:

# student_management_system.py
"""
学生成绩管理系统
功能:添加学生、查看成绩、保存/加载数据
"""
import json

class StudentManager:
    def __init__(self):
        self.students = []
        self.load_data()
    
    def add_student(self, name, scores):
        """添加学生"""
        student = {
            "name": name,
            "scores": scores,
            "average": sum(scores.values()) / len(scores)
        }
        self.students.append(student)
        print(f"已添加学生:{name}")
    
    def show_all_students(self):
        """显示所有学生"""
        if not self.students:
            print("暂无学生数据")
            return
        
        print("\n" + "="*50)
        print("学生成绩列表")
        print("="*50)
        
        for i, student in enumerate(self.students, 1):
            print(f"\n{i}. {student['name']}")
            print(f"   成绩:{student['scores']}")
            print(f"   平均分:{student['average']:.2f}")
    
    def get_top_students(self, n=3):
        """获取成绩前N名的学生"""
        sorted_students = sorted(
            self.students, 
            key=lambda x: x['average'], 
            reverse=True
        )
        return sorted_students[:n]
    
    def save_data(self):
        """保存数据到JSON文件"""
        try:
            with open("students_data.json", "w", encoding="utf-8") as file:
                json.dump(self.students, file, ensure_ascii=False, indent=2)
            print("数据已保存")
        except Exception as e:
            print(f"保存失败:{e}")
    
    def load_data(self):
        """从JSON文件加载数据"""
        try:
            with open("students_data.json", "r", encoding="utf-8") as file:
                self.students = json.load(file)
            print(f"已加载 {len(self.students)} 条学生数据")
        except FileNotFoundError:
            print("数据文件不存在,创建新数据库")
            self.students = []
        except Exception as e:
            print(f"加载失败:{e}")
            self.students = []
    
    def get_statistics(self):
        """获取统计信息"""
        if not self.students:
            return None
        
        all_averages = [s['average'] for s in self.students]
        return {
            "total_students": len(self.students),
            "class_average": sum(all_averages) / len(all_averages),
            "highest_average": max(all_averages),
            "lowest_average": min(all_averages)
        }

def main():
    """主程序"""
    manager = StudentManager()
    
    # 添加学生数据
    manager.add_student("张三", {"语文": 85, "数学": 92, "英语": 88})
    manager.add_student("李四", {"语文": 78, "数学": 95, "英语": 82})
    manager.add_student("王五", {"语文": 92, "数学": 88, "英语": 90})
    manager.add_student("赵六", {"语文": 88, "数学": 85, "英语": 87})
    
    # 显示所有学生
    manager.show_all_students()
    
    # 显示前三名
    print("\n" + "="*50)
    print("成绩前三名")
    print("="*50)
    top_students = manager.get_top_students(3)
    for i, student in enumerate(top_students, 1):
        print(f"{i}. {student['name']} - 平均分:{student['average']:.2f}")
    
    # 统计信息
    stats = manager.get_statistics()
    print("\n" + "="*50)
    print("统计信息")
    print("="*50)
    print(f"总人数:{stats['total_students']}")
    print(f"班级平均分:{stats['class_average']:.2f}")
    print(f"最高平均分:{stats['highest_average']:.2f}")
    print(f"最低平均分:{stats['lowest_average']:.2f}")
    
    # 保存数据
    manager.save_data()

if __name__ == "__main__":
    main()

学生最终挑战

选择以下一个项目完成:

项目A:图书管理系统

创建library_system.py,要求:

  • 使用列表存储图书信息(书名、作者、库存)
  • 实现添加图书、借书、还书功能
  • 使用JSON保存和加载数据
  • 实现查询功能(按书名或作者)
  • 添加异常处理

项目B:个人财务记录

创建finance_tracker.py,要求:

  • 记录收入和支出(日期、类型、金额、备注)
  • 使用CSV保存数据
  • 计算总收入、总支出、余额
  • 按类型统计支出(用字典)
  • 生成月度报告

项目C:单词本应用

创建vocabulary_app.py,要求:

  • 存储单词和释义(用字典)
  • 实现添加、删除、查询单词
  • 使用JSON保存数据
  • 实现随机测试功能(随机抽取单词)
  • 统计单词数量和学习进度

今日总结

知识点回顾

今天我们学了这些内容:

数据结构

  • 列表的高级操作:切片、排序、常用方法
  • 列表推导式:简洁创建列表
  • 字典的操作和字典推导式
  • 集合的运算和去重
  • 元组的不可变特性

文件操作

  • 文本文件的读写
  • JSON文件的处理
  • CSV文件的操作
  • with语句的使用

异常处理

  • try-except基本用法
  • 捕获多种异常
  • else和finally子句
  • 实际应用场景

作业清单

请完成以下作业,巩固今天的学习:

  1. 必做:完成所有课堂练习(练习1-8)
  2. 必做:完成一个最终挑战项目(A/B/C任选其一)
  3. 选做:优化你的项目,添加更多功能

常见问题FAQ

Q1: 列表和元组有什么区别?

A: 列表可以修改(可变),元组不能修改(不可变)。元组通常用于存储不应该改变的数据。

Q2: 什么时候用列表推导式?

A: 当你需要从一个列表创建另一个列表,并且逻辑比较简单时。如果逻辑复杂,还是用普通循环更清晰。

Q3: JSON和CSV有什么区别?

A: JSON适合存储复杂的嵌套数据结构,CSV适合存储表格数据。JSON更灵活,CSV更适合用Excel打开。

Q4: 为什么要用异常处理?

A: 异常处理可以让程序更健壮,遇到错误不会直接崩溃,而是优雅地处理错误并给用户友好的提示。

下节预告

Day 3我们会学习:

  • 面向对象编程基础
  • 类和对象的概念
  • 继承和多态
  • 特殊方法和属性

附录:快速参考

列表常用方法

方法说明示例
append(x)末尾添加元素list.append(5)
insert(i, x)指定位置插入list.insert(0, 'a')
remove(x)删除指定元素list.remove('a')
pop()删除并返回最后元素list.pop()
sort()原地排序list.sort()
reverse()反转列表list.reverse()
count(x)统计元素出现次数list.count(5)
index(x)查找元素索引list.index('a')

字典常用方法

方法说明示例
get(key, default)获取值(带默认值)dict.get('name', 'Unknown')
keys()获取所有键dict.keys()
values()获取所有值dict.values()
items()获取所有键值对dict.items()
pop(key)删除并返回值dict.pop('name')
update(other)更新字典dict.update({'age': 20})

文件操作模式

模式说明
'r'只读模式(默认)
'w'写入模式(覆盖)
'a'追加模式
'r+'读写模式
'b'二进制模式(如'rb', 'wb'

常见异常类型

异常说明
ValueError值错误(如类型转换失败)
TypeError类型错误
KeyError字典键不存在
IndexError索引超出范围
FileNotFoundError文件不存在
ZeroDivisionError除零错误

恭喜你完成Day 2的学习!今天的内容比较多,记得多练习。明天见!