今天我们要完成的目标:深入学习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}")
现在你来练习:
-
购物车管理:创建
shopping_cart.py- 创建一个空列表
cart - 添加5个商品(字符串)
- 删除第3个商品
- 在第2个位置插入一个新商品
- 打印最终的购物车
- 创建一个空列表
-
数字处理:创建
number_processor.py- 创建列表:
[10, 25, 3, 47, 15, 8, 33, 21] - 找出所有大于20的数字
- 计算所有偶数的和
- 将列表反转并打印
- 创建列表:
-
成绩分析:创建
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")
现在你来练习:
-
数字筛选:创建
number_filter.py- 创建1-50的列表
- 筛选出所有能被3整除的数
- 筛选出所有个位数是5的数
-
字符串处理:创建
string_processor.py- 创建列表:
["apple", "banana", "cherry", "date"] - 获取所有字符串的长度列表
- 筛选出长度大于5的字符串
- 创建列表:
-
成绩等级:创建
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}")
现在你来练习:
-
商品库存管理:创建
inventory.py- 创建字典存储5个商品的库存(商品名:数量)
- 添加2个新商品
- 更新某个商品的库存
- 删除一个商品
- 打印所有库存信息
-
单词计数:创建
word_counter.py- 给定句子:
"python is great and python is easy" - 统计每个单词出现的次数(用字典存储)
- 打印结果
- 给定句子:
-
成绩统计:创建
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}")
现在你来练习:
-
标签去重:创建
tag_processor.py- 创建两个文章的标签列表(有重复)
- 去重后统计每篇文章有多少个标签
- 找出两篇文章的共同标签
-
坐标处理:创建
coordinate.py- 创建5个坐标点(用元组表示)
- 计算每个点到原点的距离
- 找出距离原点最近的点
-
学生选课:创建
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())
现在你来练习:
-
待办事项:创建
todo_file.py- 创建一个待办事项列表(列表)
- 将所有待办事项写入
todo.txt文件 - 读取文件并打印所有待办事项
-
成绩记录:创建
score_file.py- 创建学生成绩字典:
{"张三": 85, "李四": 92, "王五": 78} - 将成绩写入
scores.txt,格式:姓名: 分数 - 读取文件并计算平均分
- 创建学生成绩字典:
-
文本统计:创建
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'])}")
现在你来练习:
-
学生数据库:创建
student_db.py- 创建3个学生的信息(字典列表)
- 保存到
students.json - 读取并打印所有学生信息
- 计算所有学生的平均年龄
-
购物车保存:创建
cart_storage.py- 创建购物车数据(商品列表,每个商品包含名称、价格、数量)
- 保存到
cart.json - 读取并计算总价
-
用户设置:创建
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}元")
现在你来练习:
-
员工信息表:创建
employee_data.py- 创建5个员工的信息(姓名、部门、工资)
- 写入
employees.csv - 读取并计算平均工资
- 找出工资最高的员工
-
考试成绩表:创建
exam_scores.py- 创建学生成绩表(姓名、语文、数学、英语)
- 写入
scores.csv - 读取并计算每个学生的总分
- 按总分排序并输出
-
产品库存表:创建
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()
现在你来练习:
-
文件读取器:创建
safe_file_reader.py- 定义函数读取文件内容
- 处理文件不存在的异常
- 处理编码错误的异常
- 测试读取存在和不存在的文件
-
计算器:创建
safe_calculator.py- 定义函数进行四则运算
- 处理除零异常
- 处理类型错误
- 测试各种情况
-
数据转换器:创建
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-8)
- 必做:完成一个最终挑战项目(A/B/C任选其一)
- 选做:优化你的项目,添加更多功能
常见问题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的学习!今天的内容比较多,记得多练习。明天见!