学习目标
通过本章学习,你将掌握: - 条件语句的使用(if/elif/else) - 循环语句的应用(for/while) - 循环控制语句(break/continue/pass) - 异常处理机制(try/except/finally) - 上下文管理器(with语句) - 推导式的使用
4.1 条件语句
if语句基础
# 基本if语句
age = 18
if age >= 18:
print("你已经成年了")
# if-else语句
score = 85
if score >= 60:
print("考试通过")
else:
print("考试不通过")
# if-elif-else语句
score = 92
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
elif score >= 60:
grade = "D"
else:
grade = "F"
print(f"你的成绩等级是: {grade}")
# 嵌套if语句
weather = "sunny"
temperature = 25
if weather == "sunny":
if temperature > 20:
print("天气很好,适合外出")
else:
print("天气晴朗但有点冷")
else:
print("天气不太好")
条件表达式(三元运算符)
# 条件表达式的语法:value_if_true if condition else value_if_false
age = 20
status = "成年人" if age >= 18 else "未成年人"
print(f"你是{status}")
# 比较传统写法
if age >= 18:
status = "成年人"
else:
status = "未成年人"
# 更复杂的条件表达式
score = 85
result = "优秀" if score >= 90 else "良好" if score >= 80 else "及格" if score >= 60 else "不及格"
print(f"成绩评价: {result}")
# 在函数调用中使用
def get_discount(is_member, purchase_amount):
return 0.1 if is_member else 0.05 if purchase_amount > 100 else 0
discount = get_discount(True, 150)
print(f"折扣率: {discount:.1%}")
# 在列表操作中使用
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_or_odd = ["偶数" if x % 2 == 0 else "奇数" for x in numbers]
print(even_or_odd)
复杂条件判断
# 多条件组合
username = "admin"
password = "123456"
is_active = True
if username == "admin" and password == "123456" and is_active:
print("登录成功")
else:
print("登录失败")
# 使用in操作符
user_role = "manager"
allowed_roles = ["admin", "manager", "supervisor"]
if user_role in allowed_roles:
print("有权限访问")
else:
print("权限不足")
# 检查多个条件
age = 25
income = 50000
credit_score = 750
# 贷款审批条件
if (age >= 18 and age <= 65) and income >= 30000 and credit_score >= 700:
print("贷款申请通过")
else:
reasons = []
if not (18 <= age <= 65):
reasons.append("年龄不符合要求")
if income < 30000:
reasons.append("收入不足")
if credit_score < 700:
reasons.append("信用评分过低")
print(f"贷款申请被拒绝,原因: {', '.join(reasons)}")
# 使用any()和all()函数
scores = [85, 92, 78, 96, 88]
# 检查是否所有成绩都及格
if all(score >= 60 for score in scores):
print("所有科目都及格")
else:
print("有科目不及格")
# 检查是否有优秀成绩
if any(score >= 90 for score in scores):
print("有优秀成绩")
else:
print("没有优秀成绩")
4.2 循环语句
for循环
# 遍历列表
fruits = ["apple", "banana", "orange", "grape"]
for fruit in fruits:
print(f"我喜欢{fruit}")
# 遍历字符串
word = "Python"
for char in word:
print(char, end=" ")
print() # 换行
# 使用range()函数
print("使用range(5):")
for i in range(5):
print(i, end=" ")
print()
print("使用range(1, 6):")
for i in range(1, 6):
print(i, end=" ")
print()
print("使用range(0, 10, 2):")
for i in range(0, 10, 2):
print(i, end=" ")
print()
# 遍历字典
student = {"name": "Alice", "age": 20, "major": "Computer Science"}
# 遍历键
print("遍历键:")
for key in student:
print(key)
# 遍历值
print("遍历值:")
for value in student.values():
print(value)
# 遍历键值对
print("遍历键值对:")
for key, value in student.items():
print(f"{key}: {value}")
# 使用enumerate()获取索引
fruits = ["apple", "banana", "orange"]
for index, fruit in enumerate(fruits):
print(f"{index}: {fruit}")
# 从指定索引开始
for index, fruit in enumerate(fruits, start=1):
print(f"第{index}个水果: {fruit}")
# 使用zip()同时遍历多个序列
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
cities = ["北京", "上海", "广州"]
for name, age, city in zip(names, ages, cities):
print(f"{name}, {age}岁, 来自{city}")
# 嵌套循环
print("九九乘法表:")
for i in range(1, 10):
for j in range(1, i + 1):
print(f"{j}×{i}={i*j}", end="\t")
print() # 换行
while循环
# 基本while循环
count = 0
while count < 5:
print(f"计数: {count}")
count += 1
# 用户输入验证
while True:
password = input("请输入密码: ")
if password == "123456":
print("密码正确")
break
else:
print("密码错误,请重试")
# 计算数字的各位数字之和
number = 12345
digit_sum = 0
temp = number
while temp > 0:
digit = temp % 10
digit_sum += digit
temp //= 10
print(f"{number}的各位数字之和是: {digit_sum}")
# 猜数字游戏
import random
target = random.randint(1, 100)
attempts = 0
max_attempts = 7
print("猜数字游戏!我想了一个1-100之间的数字。")
print(f"你有{max_attempts}次机会。")
while attempts < max_attempts:
try:
guess = int(input(f"第{attempts + 1}次猜测: "))
attempts += 1
if guess == target:
print(f"恭喜!你猜对了!数字是{target}")
print(f"你用了{attempts}次猜测")
break
elif guess < target:
print("太小了!")
else:
print("太大了!")
remaining = max_attempts - attempts
if remaining > 0:
print(f"还有{remaining}次机会")
except ValueError:
print("请输入有效的数字")
attempts -= 1 # 无效输入不计入尝试次数
else:
print(f"游戏结束!正确答案是{target}")
循环控制语句
# break语句:跳出循环
print("使用break:")
for i in range(10):
if i == 5:
break
print(i, end=" ")
print("\n循环结束")
# continue语句:跳过当前迭代
print("使用continue(跳过偶数):")
for i in range(10):
if i % 2 == 0:
continue
print(i, end=" ")
print("\n循环结束")
# pass语句:占位符
print("使用pass:")
for i in range(5):
if i == 2:
pass # 什么都不做,占位符
print(i, end=" ")
print("\n循环结束")
# 在嵌套循环中使用break和continue
print("嵌套循环中的break:")
for i in range(3):
print(f"外层循环 i={i}")
for j in range(5):
if j == 3:
break # 只跳出内层循环
print(f" 内层循环 j={j}")
# 使用标志变量跳出嵌套循环
print("使用标志变量跳出嵌套循环:")
found = False
for i in range(3):
if found:
break
for j in range(5):
if i == 1 and j == 2:
print(f"找到目标: i={i}, j={j}")
found = True
break
print(f"i={i}, j={j}")
# else子句:循环正常结束时执行
print("for循环的else子句:")
for i in range(5):
print(i, end=" ")
else:
print("\n循环正常结束")
print("被break中断的循环:")
for i in range(5):
if i == 3:
break
print(i, end=" ")
else:
print("\n循环正常结束") # 这行不会执行
print("循环被中断")
4.3 异常处理
基本异常处理
# 基本try-except结构
try:
number = int(input("请输入一个数字: "))
result = 10 / number
print(f"10 / {number} = {result}")
except ValueError:
print("输入的不是有效数字")
except ZeroDivisionError:
print("不能除以零")
# 捕获多种异常
try:
data = [1, 2, 3]
index = int(input("请输入索引: "))
print(f"data[{index}] = {data[index]}")
except (ValueError, IndexError) as e:
print(f"发生错误: {e}")
# 捕获所有异常
try:
# 一些可能出错的代码
result = eval(input("请输入一个表达式: "))
print(f"结果: {result}")
except Exception as e:
print(f"发生未知错误: {type(e).__name__}: {e}")
# try-except-else-finally结构
def safe_divide(a, b):
try:
result = a / b
except ZeroDivisionError:
print("错误:除数不能为零")
return None
except TypeError:
print("错误:参数类型不正确")
return None
else:
print("计算成功")
return result
finally:
print("清理工作完成")
print(safe_divide(10, 2))
print(safe_divide(10, 0))
print(safe_divide("10", 2))
自定义异常
# 定义自定义异常类
class CustomError(Exception):
"""自定义异常基类"""
pass
class ValidationError(CustomError):
"""验证错误"""
def __init__(self, message, field=None):
super().__init__(message)
self.field = field
class BusinessLogicError(CustomError):
"""业务逻辑错误"""
pass
# 使用自定义异常
def validate_age(age):
if not isinstance(age, int):
raise ValidationError("年龄必须是整数", "age")
if age < 0:
raise ValidationError("年龄不能为负数", "age")
if age > 150:
raise ValidationError("年龄不能超过150岁", "age")
return True
def process_user_registration(name, age, email):
try:
# 验证输入
if not name.strip():
raise ValidationError("姓名不能为空", "name")
validate_age(age)
if "@" not in email:
raise ValidationError("邮箱格式不正确", "email")
# 模拟业务逻辑
if age < 18:
raise BusinessLogicError("用户必须年满18岁才能注册")
print(f"用户 {name} 注册成功")
return True
except ValidationError as e:
print(f"验证错误 ({e.field}): {e}")
return False
except BusinessLogicError as e:
print(f"业务逻辑错误: {e}")
return False
except Exception as e:
print(f"系统错误: {e}")
return False
# 测试自定义异常
process_user_registration("Alice", 25, "alice@example.com")
process_user_registration("", 25, "alice@example.com")
process_user_registration("Bob", -5, "bob@example.com")
process_user_registration("Charlie", 16, "charlie@example.com")
异常处理最佳实践
import logging
import traceback
from typing import Optional, Union
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
class FileProcessor:
"""文件处理器示例"""
def __init__(self, filename: str):
self.filename = filename
def read_file(self) -> Optional[str]:
"""安全地读取文件"""
try:
with open(self.filename, 'r', encoding='utf-8') as file:
content = file.read()
logger.info(f"成功读取文件: {self.filename}")
return content
except FileNotFoundError:
logger.error(f"文件不存在: {self.filename}")
return None
except PermissionError:
logger.error(f"没有权限读取文件: {self.filename}")
return None
except UnicodeDecodeError:
logger.error(f"文件编码错误: {self.filename}")
return None
except Exception as e:
logger.error(f"读取文件时发生未知错误: {e}")
logger.debug(traceback.format_exc()) # 记录完整的错误堆栈
return None
def write_file(self, content: str) -> bool:
"""安全地写入文件"""
try:
with open(self.filename, 'w', encoding='utf-8') as file:
file.write(content)
logger.info(f"成功写入文件: {self.filename}")
return True
except PermissionError:
logger.error(f"没有权限写入文件: {self.filename}")
return False
except OSError as e:
logger.error(f"写入文件时发生系统错误: {e}")
return False
except Exception as e:
logger.error(f"写入文件时发生未知错误: {e}")
return False
# 重试机制
def retry_operation(func, max_attempts=3, delay=1):
"""重试装饰器"""
import time
def wrapper(*args, **kwargs):
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts - 1:
logger.error(f"操作失败,已重试{max_attempts}次: {e}")
raise
else:
logger.warning(f"操作失败,第{attempt + 1}次重试: {e}")
time.sleep(delay)
return wrapper
# 使用重试机制
@retry_operation
def unreliable_network_call():
import random
if random.random() < 0.7: # 70%的概率失败
raise ConnectionError("网络连接失败")
return "网络请求成功"
# 测试异常处理
if __name__ == "__main__":
# 测试文件处理
processor = FileProcessor("test.txt")
# 写入测试内容
if processor.write_file("这是测试内容\n第二行内容"):
# 读取内容
content = processor.read_file()
if content:
print(f"文件内容:\n{content}")
# 测试重试机制
try:
result = unreliable_network_call()
print(result)
except Exception as e:
print(f"最终失败: {e}")
4.4 上下文管理器
with语句基础
# 传统文件操作(不推荐)
file = open("example.txt", "w")
try:
file.write("Hello, World!")
finally:
file.close()
# 使用with语句(推荐)
with open("example.txt", "w", encoding="utf-8") as file:
file.write("Hello, World!")
# 文件会自动关闭
# 同时打开多个文件
with open("input.txt", "r", encoding="utf-8") as infile, \
open("output.txt", "w", encoding="utf-8") as outfile:
content = infile.read()
outfile.write(content.upper())
# 自定义上下文管理器
class Timer:
"""计时器上下文管理器"""
def __init__(self, name="操作"):
self.name = name
def __enter__(self):
import time
self.start_time = time.time()
print(f"{self.name}开始...")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
import time
end_time = time.time()
duration = end_time - self.start_time
print(f"{self.name}完成,耗时: {duration:.2f}秒")
if exc_type is not None:
print(f"发生异常: {exc_type.__name__}: {exc_val}")
return False # 不抑制异常
# 使用自定义上下文管理器
with Timer("数据处理"):
import time
time.sleep(1) # 模拟耗时操作
data = [i ** 2 for i in range(1000000)]
print(f"处理了{len(data)}个数据")
# 使用contextlib模块
from contextlib import contextmanager
@contextmanager
def database_connection():
"""数据库连接上下文管理器"""
print("连接数据库...")
connection = "数据库连接对象" # 模拟连接
try:
yield connection
except Exception as e:
print(f"数据库操作出错: {e}")
print("回滚事务...")
raise
else:
print("提交事务...")
finally:
print("关闭数据库连接")
# 使用数据库连接
with database_connection() as conn:
print(f"使用连接: {conn}")
print("执行数据库操作...")
# 异常抑制
from contextlib import suppress
# 忽略特定异常
with suppress(FileNotFoundError):
with open("nonexistent.txt", "r") as f:
content = f.read()
print("程序继续执行...")
# 临时改变工作目录
import os
from contextlib import contextmanager
@contextmanager
def change_directory(path):
"""临时改变工作目录"""
old_path = os.getcwd()
try:
os.chdir(path)
yield
finally:
os.chdir(old_path)
# 使用目录切换
print(f"当前目录: {os.getcwd()}")
with change_directory("/tmp" if os.name != 'nt' else "C:\\temp"):
print(f"临时目录: {os.getcwd()}")
print(f"恢复目录: {os.getcwd()}")
4.5 推导式
列表推导式
# 基本列表推导式
numbers = [1, 2, 3, 4, 5]
squares = [x ** 2 for x in numbers]
print(f"平方数: {squares}")
# 带条件的列表推导式
even_squares = [x ** 2 for x in numbers if x % 2 == 0]
print(f"偶数的平方: {even_squares}")
# 复杂表达式
words = ["hello", "world", "python", "programming"]
capitalized = [word.capitalize() for word in words if len(word) > 5]
print(f"长度大于5的单词(首字母大写): {capitalized}")
# 嵌套循环
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [item for row in matrix for item in row]
print(f"展平的矩阵: {flattened}")
# 条件表达式
numbers = [-2, -1, 0, 1, 2]
abs_numbers = [x if x >= 0 else -x for x in numbers]
print(f"绝对值: {abs_numbers}")
# 字符串处理
sentence = "Hello World Python Programming"
words = sentence.split()
word_lengths = [len(word) for word in words]
print(f"单词长度: {word_lengths}")
# 生成坐标点
coordinates = [(x, y) for x in range(3) for y in range(3)]
print(f"坐标点: {coordinates}")
# 过滤和转换
data = ["1", "2", "abc", "4", "5.5", "def"]
numbers = [float(x) for x in data if x.replace('.', '').isdigit()]
print(f"提取的数字: {numbers}")
字典推导式
# 基本字典推导式
numbers = [1, 2, 3, 4, 5]
square_dict = {x: x ** 2 for x in numbers}
print(f"数字和其平方: {square_dict}")
# 从两个列表创建字典
keys = ["name", "age", "city"]
values = ["Alice", 25, "Beijing"]
person = {k: v for k, v in zip(keys, values)}
print(f"个人信息: {person}")
# 字典过滤和转换
original_dict = {"a": 1, "b": 2, "c": 3, "d": 4}
filtered_dict = {k: v * 2 for k, v in original_dict.items() if v % 2 == 0}
print(f"偶数值翻倍: {filtered_dict}")
# 字符串统计
text = "hello world"
char_count = {char: text.count(char) for char in set(text) if char != ' '}
print(f"字符计数: {char_count}")
# 嵌套字典
students = ["Alice", "Bob", "Charlie"]
subjects = ["Math", "English", "Science"]
grades = {student: {subject: 0 for subject in subjects} for student in students}
print(f"成绩表结构: {grades}")
# 反转字典
original = {"a": 1, "b": 2, "c": 3}
reversed_dict = {v: k for k, v in original.items()}
print(f"反转字典: {reversed_dict}")
集合推导式
# 基本集合推导式
numbers = [1, 2, 2, 3, 3, 4, 5]
unique_squares = {x ** 2 for x in numbers}
print(f"唯一平方数: {unique_squares}")
# 字符串处理
sentence = "Hello World Python Programming"
unique_chars = {char.lower() for char in sentence if char.isalpha()}
print(f"唯一字符: {unique_chars}")
# 数学运算
primes_under_20 = {x for x in range(2, 20) if all(x % i != 0 for i in range(2, int(x**0.5) + 1))}
print(f"20以下的质数: {primes_under_20}")
# 集合运算
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
common_squares = {x ** 2 for x in set1 if x in set2}
print(f"交集的平方: {common_squares}")
生成器表达式
# 生成器表达式(惰性求值)
numbers = (x ** 2 for x in range(10))
print(f"生成器对象: {numbers}")
print(f"生成器内容: {list(numbers)}")
# 内存效率比较
import sys
# 列表推导式(立即计算)
list_comp = [x ** 2 for x in range(1000)]
print(f"列表推导式内存占用: {sys.getsizeof(list_comp)} 字节")
# 生成器表达式(惰性计算)
gen_exp = (x ** 2 for x in range(1000))
print(f"生成器表达式内存占用: {sys.getsizeof(gen_exp)} 字节")
# 在函数中使用生成器表达式
numbers = range(1, 11)
total = sum(x ** 2 for x in numbers if x % 2 == 0)
print(f"偶数平方和: {total}")
# 链式生成器
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# 获取前10个斐波那契数的平方
fib_squares = (x ** 2 for x in fibonacci())
first_10_squares = [next(fib_squares) for _ in range(10)]
print(f"前10个斐波那契数的平方: {first_10_squares}")
# 文件处理生成器
def read_large_file(filename):
"""逐行读取大文件"""
try:
with open(filename, 'r', encoding='utf-8') as file:
for line in file:
yield line.strip()
except FileNotFoundError:
print(f"文件 {filename} 不存在")
return
# 处理文件内容
filename = "large_file.txt"
with open(filename, 'w', encoding='utf-8') as f:
for i in range(100):
f.write(f"这是第{i+1}行\n")
# 使用生成器处理文件
long_lines = (line for line in read_large_file(filename) if len(line) > 10)
for i, line in enumerate(long_lines):
if i >= 5: # 只显示前5行
break
print(f"长行 {i+1}: {line}")
4.6 综合示例:学生成绩管理系统
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
学生成绩管理系统
功能:
1. 添加学生和成绩
2. 查询学生信息
3. 统计成绩
4. 生成报告
作者: Python学习者
版本: 1.0
"""
import json
import statistics
from typing import Dict, List, Optional, Tuple
from contextlib import contextmanager
class Student:
"""学生类"""
def __init__(self, student_id: str, name: str, age: int):
self.student_id = student_id
self.name = name
self.age = age
self.grades: Dict[str, float] = {}
def add_grade(self, subject: str, grade: float) -> None:
"""添加成绩"""
if not 0 <= grade <= 100:
raise ValueError("成绩必须在0-100之间")
self.grades[subject] = grade
def get_average(self) -> float:
"""计算平均分"""
if not self.grades:
return 0.0
return statistics.mean(self.grades.values())
def get_grade_level(self) -> str:
"""获取成绩等级"""
avg = self.get_average()
if avg >= 90:
return "优秀"
elif avg >= 80:
return "良好"
elif avg >= 70:
return "中等"
elif avg >= 60:
return "及格"
else:
return "不及格"
def to_dict(self) -> dict:
"""转换为字典"""
return {
"student_id": self.student_id,
"name": self.name,
"age": self.age,
"grades": self.grades
}
@classmethod
def from_dict(cls, data: dict) -> 'Student':
"""从字典创建学生对象"""
student = cls(data["student_id"], data["name"], data["age"])
student.grades = data["grades"]
return student
def __str__(self) -> str:
return f"学生({self.student_id}): {self.name}, {self.age}岁, 平均分: {self.get_average():.1f}"
class GradeManager:
"""成绩管理器"""
def __init__(self, filename: str = "students.json"):
self.filename = filename
self.students: Dict[str, Student] = {}
self.load_data()
@contextmanager
def auto_save(self):
"""自动保存上下文管理器"""
try:
yield
finally:
self.save_data()
def add_student(self, student_id: str, name: str, age: int) -> bool:
"""添加学生"""
try:
if student_id in self.students:
raise ValueError(f"学生ID {student_id} 已存在")
if not name.strip():
raise ValueError("姓名不能为空")
if not 6 <= age <= 100:
raise ValueError("年龄必须在6-100之间")
with self.auto_save():
self.students[student_id] = Student(student_id, name, age)
print(f"成功添加学生: {name}")
return True
except ValueError as e:
print(f"添加学生失败: {e}")
return False
def add_grade(self, student_id: str, subject: str, grade: float) -> bool:
"""添加成绩"""
try:
if student_id not in self.students:
raise ValueError(f"学生ID {student_id} 不存在")
with self.auto_save():
self.students[student_id].add_grade(subject, grade)
print(f"成功为学生 {student_id} 添加 {subject} 成绩: {grade}")
return True
except ValueError as e:
print(f"添加成绩失败: {e}")
return False
def get_student(self, student_id: str) -> Optional[Student]:
"""获取学生信息"""
return self.students.get(student_id)
def search_students(self, keyword: str) -> List[Student]:
"""搜索学生"""
keyword = keyword.lower()
return [
student for student in self.students.values()
if keyword in student.name.lower() or keyword in student.student_id.lower()
]
def get_class_statistics(self) -> Dict[str, float]:
"""获取班级统计信息"""
if not self.students:
return {}
all_averages = [student.get_average() for student in self.students.values() if student.grades]
if not all_averages:
return {}
return {
"班级平均分": statistics.mean(all_averages),
"最高平均分": max(all_averages),
"最低平均分": min(all_averages),
"标准差": statistics.stdev(all_averages) if len(all_averages) > 1 else 0
}
def get_subject_statistics(self, subject: str) -> Dict[str, float]:
"""获取科目统计信息"""
grades = [
student.grades[subject] for student in self.students.values()
if subject in student.grades
]
if not grades:
return {}
return {
"平均分": statistics.mean(grades),
"最高分": max(grades),
"最低分": min(grades),
"及格率": len([g for g in grades if g >= 60]) / len(grades) * 100
}
def generate_report(self) -> str:
"""生成报告"""
report = ["\n" + "=" * 50]
report.append(" 学生成绩报告")
report.append("=" * 50)
# 学生总数
report.append(f"学生总数: {len(self.students)}")
# 班级统计
class_stats = self.get_class_statistics()
if class_stats:
report.append("\n班级统计:")
for key, value in class_stats.items():
report.append(f" {key}: {value:.2f}")
# 各等级人数统计
grade_levels = {"优秀": 0, "良好": 0, "中等": 0, "及格": 0, "不及格": 0}
for student in self.students.values():
if student.grades:
level = student.get_grade_level()
grade_levels[level] += 1
report.append("\n成绩等级分布:")
for level, count in grade_levels.items():
percentage = count / len(self.students) * 100 if self.students else 0
report.append(f" {level}: {count}人 ({percentage:.1f}%)")
# 科目统计
all_subjects = set()
for student in self.students.values():
all_subjects.update(student.grades.keys())
if all_subjects:
report.append("\n科目统计:")
for subject in sorted(all_subjects):
stats = self.get_subject_statistics(subject)
if stats:
report.append(f" {subject}:")
report.append(f" 平均分: {stats['平均分']:.2f}")
report.append(f" 最高分: {stats['最高分']:.1f}")
report.append(f" 最低分: {stats['最低分']:.1f}")
report.append(f" 及格率: {stats['及格率']:.1f}%")
# 优秀学生
excellent_students = [
student for student in self.students.values()
if student.grades and student.get_average() >= 90
]
if excellent_students:
report.append("\n优秀学生 (平均分≥90):")
for student in sorted(excellent_students, key=lambda s: s.get_average(), reverse=True):
report.append(f" {student.name} ({student.student_id}): {student.get_average():.1f}分")
report.append("=" * 50)
return "\n".join(report)
def save_data(self) -> None:
"""保存数据到文件"""
try:
data = {sid: student.to_dict() for sid, student in self.students.items()}
with open(self.filename, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
except Exception as e:
print(f"保存数据失败: {e}")
def load_data(self) -> None:
"""从文件加载数据"""
try:
with open(self.filename, 'r', encoding='utf-8') as f:
data = json.load(f)
self.students = {
sid: Student.from_dict(student_data)
for sid, student_data in data.items()
}
except FileNotFoundError:
print(f"数据文件 {self.filename} 不存在,将创建新文件")
except Exception as e:
print(f"加载数据失败: {e}")
def main():
"""主函数"""
manager = GradeManager()
while True:
print("\n" + "=" * 30)
print(" 学生成绩管理系统")
print("=" * 30)
print("1. 添加学生")
print("2. 添加成绩")
print("3. 查询学生")
print("4. 搜索学生")
print("5. 生成报告")
print("6. 退出")
try:
choice = input("\n请选择操作 (1-6): ").strip()
if choice == '1':
student_id = input("请输入学生ID: ").strip()
name = input("请输入姓名: ").strip()
age = int(input("请输入年龄: "))
manager.add_student(student_id, name, age)
elif choice == '2':
student_id = input("请输入学生ID: ").strip()
subject = input("请输入科目: ").strip()
grade = float(input("请输入成绩: "))
manager.add_grade(student_id, subject, grade)
elif choice == '3':
student_id = input("请输入学生ID: ").strip()
student = manager.get_student(student_id)
if student:
print(f"\n{student}")
if student.grades:
print("各科成绩:")
for subject, grade in student.grades.items():
print(f" {subject}: {grade}")
print(f"成绩等级: {student.get_grade_level()}")
else:
print("暂无成绩记录")
else:
print("学生不存在")
elif choice == '4':
keyword = input("请输入搜索关键字: ").strip()
students = manager.search_students(keyword)
if students:
print(f"\n找到 {len(students)} 个学生:")
for student in students:
print(f" {student}")
else:
print("未找到匹配的学生")
elif choice == '5':
report = manager.generate_report()
print(report)
# 询问是否保存报告
save_report = input("\n是否保存报告到文件? (y/n): ").lower().strip()
if save_report in ['y', 'yes', '是']:
with open("grade_report.txt", 'w', encoding='utf-8') as f:
f.write(report)
print("报告已保存到 grade_report.txt")
elif choice == '6':
print("感谢使用学生成绩管理系统!")
break
else:
print("无效的选择,请重新输入")
except ValueError as e:
print(f"输入错误: {e}")
except KeyboardInterrupt:
print("\n\n程序被用户中断")
break
except Exception as e:
print(f"发生错误: {e}")
if __name__ == "__main__":
# 添加一些测试数据
manager = GradeManager()
# 添加测试学生
test_students = [
("001", "张三", 20),
("002", "李四", 19),
("003", "王五", 21),
("004", "赵六", 20)
]
for sid, name, age in test_students:
manager.add_student(sid, name, age)
# 添加测试成绩
test_grades = [
("001", "数学", 95),
("001", "英语", 88),
("001", "物理", 92),
("002", "数学", 78),
("002", "英语", 85),
("002", "物理", 80),
("003", "数学", 65),
("003", "英语", 70),
("003", "物理", 68),
("004", "数学", 58),
("004", "英语", 62),
("004", "物理", 55)
]
for sid, subject, grade in test_grades:
manager.add_grade(sid, subject, grade)
# 启动主程序
main()
运行成绩管理系统:
python grade_manager.py
本章小结
本章我们学习了Python的控制结构:
- 条件语句:if/elif/else语句、条件表达式、复杂条件判断
- 循环语句:for循环、while循环、循环控制语句
- 异常处理:try/except/finally、自定义异常、异常处理最佳实践
- 上下文管理器:with语句、自定义上下文管理器
- 推导式:列表、字典、集合推导式、生成器表达式
- 综合应用:通过学生成绩管理系统整合所学知识
下一章预告
下一章我们将学习《数据结构》,内容包括: - 列表的高级操作 - 元组和命名元组 - 字典的高级用法 - 集合操作 - 字符串的深入应用
练习题
基础练习
条件判断:
- 编写程序判断一个年份是否为闰年
- 实现简单的计算器(支持四则运算)
- 编写程序判断三角形的类型(等边、等腰、普通)
循环练习:
- 使用for循环打印九九乘法表
- 编写程序计算1到100的质数
- 实现猜数字游戏
进阶练习
异常处理:
- 编写安全的文件读写函数
- 实现带重试机制的网络请求模拟
- 创建自定义异常类处理业务逻辑错误
推导式:
- 使用列表推导式处理嵌套列表
- 用字典推导式统计文本中的词频
- 实现生成器函数处理大数据
综合练习
- 项目实战:
- 扩展学生成绩管理系统,添加更多功能
- 实现简单的图书管理系统
- 创建命令行版本的待办事项管理器
提示:控制结构是编程的核心,多练习不同场景下的应用,培养逻辑思维能力。