一、整体结构梳理
import os # 导入模块(类似 Java import)
class Student: # 类定义(类似 Java class,但无访问修饰符)
- 构造方法 __init__()
- 实例变量:sid, name, age, _score
- @property + setter:实现 getter/setter 并带校验
- __str__():类似 toString()
- @classmethod from_string():静态工厂方法
class StudentManager: # 业务逻辑 + 持久化
- 类常量 FILE_NAME
- 构造方法 __init__():自动加载文件
- load_from_file() / save_to_file():文件读写
- add_student() / show_all() / search() / modify() / delete()
- run():主菜单循环
if __name__ == "__main__": # 程序入口(类似 Java main 方法)
二、关键差异注释(可直接对照代码理解)
1. import os vs import java.io.*
- Python 用
import 模块名,模块是.py文件或内置库。 - Java 按包导入类,
import java.util.*。
2. class Student: vs public class Student { ... }
- Python 没有
public/private/protected,所有成员默认公开。 - 约定:
_score前加一个下划线表示"受保护",两个下划线__score表示"私有"(名称修饰)。
3. def __init__(self, sid, name, age, score): vs 构造方法
self相当于 Java 的this,但必须显式作为第一个参数。- Python 构造方法固定名
__init__,在对象创建后初始化。
4. 实例变量赋值 self.sid = sid vs this.sid = sid
- Python 变量不需要提前声明,直接赋值即创建。
- Java 必须在类中声明字段。
5. @property 和 @score.setter 实现 getter/setter
python
@property
def score(self):
return self._score
@score.setter
def score(self, value):
if 0 <= value <= 100:
self._score = value
else:
raise ValueError(...)
- 调用时像普通属性:
stu.score = 90会触发 setter,print(stu.score)触发 getter。 - Java 需要手写
getScore()/setScore(int value)。
6. __str__(self) vs toString()
- 返回字符串,被
print(stu)或str(stu)自动调用。 - Java 需要显式调用
toString()或系统自动调用。
7. @classmethod 与 cls 参数
python
@classmethod
def from_string(cls, line):
sid, name, age, score = line.strip().split(',')
return cls(sid, name, int(age), float(score))
- 相当于 Java 的
public static Student fromString(String line)。 cls代表当前类(可被子类继承时正确创建对象)。
8. 文件操作 with open(...) as f vs try-with-resources
python
with open(self.FILE_NAME, "r", encoding="utf-8") as f:
for line in f:
...
with会自动关闭文件,类似 Java 的try (FileReader fr = ...)。open返回文件对象,for line in f直接逐行迭代。
9. 字典 self.students = {} vs Map<String, Student>
- 赋值:
self.students[sid] = stu - 取值:
stu = self.students.get(sid)(不存在返回None) - 删除:
del self.students[sid] - 遍历:
for stu in self.students.values():
10. try...except 异常处理 vs try...catch
python
try:
age = int(input("请输入年龄: "))
except ValueError:
print("年龄必须是数字")
- Python 使用
except ValueError as e捕获具体异常。 - 没有
finally时可以用else(当无异常时执行)。
11. input() 控制台输入 vs Scanner
input("提示")直接返回字符串(阻塞等待)。- 需要转换类型:
int(input())、float(input())。
12. 主菜单 if __name__ == "__main__": vs public static void main
- 当该脚本被直接运行时,
__name__等于"__main__",才会执行下方代码。 - 如果被其他模块导入,则不会执行,避免副作用。
三、代码中已隐式使用的 Python 特色(帮你总结)
| Python 写法 | 对应 Java 做法 |
|---|---|
stu = Student(...) |
Student stu = new Student(...) |
self.students = {} |
Map<String, Student> students = new HashMap<>() |
if sid in self.students |
if (students.containsKey(sid)) |
del self.students[sid] |
students.remove(sid) |
for stu in ...values() |
for (Student stu : students.values()) |
raise ValueError(...) |
throw new IllegalArgumentException(...) |
print(f"{stu}") |
System.out.println(stu) |
line.strip().split(',') |
line.trim().split(",") |
四、运行该程序的建议步骤
- 将代码保存为
student_manager.py - 在终端执行
python student_manager.py - 按菜单提示操作,数据会保存在同目录的
students.txt文件中
如果你希望我直接在原代码上逐行添加「Java对比」注释,也可以告诉我,我会生成一个带详细注释的代码版本。这样你一边看代码,一边对照解释,学得更快。
python
import os
class Student: # 类定义(类似 Java class,但无访问修饰符)
"""对应 Java 的 Student POJO"""
def __init__(self, sid, name, age, score):
self.sid = sid # 实例变量,类似 private 字段但无修饰符
self.name = name
self.age = age
self._score = None # 为使用 property 预设实际存储变量
self.score = score # 触发 setter 校验
# @property + setter:实现 getter/setter 并带校验
@property
def score(self):
"""成绩 getter,Java 的 getScore() """
return self._score
@score.setter
def score(self, value):
"""成绩 setter,带校验,Java 的 setScore()"""
if 0 <= value <= 100:
self._score = value
else:
raise ValueError("成绩必须在0-100之间")
def __str__(self):
"""类似 Java 的 toString()"""
return f"{self.sid},{self.name},{self.age},{self.score}"
@classmethod
def from_string(cls, line):
"""工厂方法,相当于 Java 的静态工厂 Student.fromCsv(line)"""
sid, name, age, score = line.strip().split(',')
return cls(sid, name, int(age), float(score))
class StudentManager: # 业务逻辑 + 持久化
"""相当于 DAO + Service,管理一组学生,持久化到文件"""
FILE_NAME = "students.txt" # 类常量,类似于 static final
def __init__(self):
# 用字典存储,sid -> Student,相当于 Map<String, Student>
self.students = {}
self.load_from_file()
def load_from_file(self): #文件读写
"""读取文件初始化,类似从数据库加载数据"""
try:
with open(self.FILE_NAME, "r", encoding="utf-8") as f:
for line in f:
if line.strip():
stu = Student.from_string(line)
self.students[stu.sid] = stu
except FileNotFoundError:
pass # 没有文件则忽略
def save_to_file(self):#文件读写
"""持久化写入文件"""
with open(self.FILE_NAME, "w", encoding="utf-8") as f:
for stu in self.students.values():
f.write(str(stu) + "\n")
def add_student(self):
"""添加,对比 Java 中读取 Scanner 输入"""
sid = input("请输入学号: ").strip()
if sid in self.students: # 字典的 in 操作,类似 map.containsKey()
print("该学号已存在!")
return
name = input("请输入姓名: ").strip()
try:
age = int(input("请输入年龄: "))
score = float(input("请输入成绩: "))
except ValueError:
print("年龄和成绩必须是数字")
return
try:
self.students[sid] = Student(sid, name, age, score)
self.save_to_file()
print("添加成功!")
except ValueError as e:
print(f"错误: {e}")
def show_all(self):
"""显示全部,对应遍历 map.values()"""
if not self.students:
print("暂无学生数据")
return
print("学号\t姓名\t年龄\t成绩")
print("-" * 30)
for stu in self.students.values():
print(f"{stu.sid}\t{stu.name}\t{stu.age}\t{stu.score}")
def search_student(self):
sid = input("请输入要查找的学号: ").strip()
stu = self.students.get(sid) # get() 不会抛出异常,返回 None
if stu:
print(stu)
else:
print("未找到该学生")
def modify_student(self):
sid = input("请输入要修改的学号: ").strip()
stu = self.students.get(sid)
if not stu:
print("未找到该学生")
return
print("当前信息:", stu)
name = input("新姓名(回车保持不变): ").strip()
if name:
stu.name = name
age_str = input("新年龄(回车保持不变): ").strip()
if age_str:
try:
stu.age = int(age_str)
except ValueError:
print("年龄格式错误,保留原值")
score_str = input("新成绩(回车保持不变): ").strip()
if score_str:
try:
stu.score = float(score_str) # 会触发property校验
except ValueError as e:
print(f"成绩更新失败: {e}")
self.save_to_file()
print("修改完成!")
def delete_student(self):
sid = input("请输入要删除的学号: ").strip()
if sid in self.students:
del self.students[sid] # 相当于 map.remove(key)
self.save_to_file()
print("删除成功!")
else:
print("未找到该学生")
def run(self):
"""主菜单循环,对比 while(true) + switch"""
while True:
print("\n====== 学生管理系统 ======")
print("1. 添加学生")
print("2. 显示所有学生")
print("3. 查找学生")
print("4. 修改学生")
print("5. 删除学生")
print("6. 退出")
choice = input("请选择: ").strip()
if choice == "1":
self.add_student()
elif choice == "2":
self.show_all()
elif choice == "3":
self.search_student()
elif choice == "4":
self.modify_student()
elif choice == "5":
self.delete_student()
elif choice == "6":
print("再见!")
break
else:
print("无效选择,请重新输入")
if __name__ == "__main__":
manager = StudentManager()
manager.run()