まとめ:学生記録システム
CoddyのPythonジャーニー「Object Oriented Programming」セクションの一部 — レッスン 32/64。
チャレンジ
中級このチャレンジでは、完全な学生記録管理システムを実装します。
このチャレンジを完了するには、2つのファイルを編集する必要があります。
student.py- 適切なカプセル化を備えたStudentクラスを実装しますstudentregistry.py- 学生を管理するためのStudentRegistryクラスを実装します
ステップバイステップのガイダンスについては、各ファイル内の詳細な TODO コメントに従ってください。実装は、以下を検証する包括的なテストケースに対してテストされます。
- 適切な属性のバリデーションとエラーハンドリング
- 成績平均の正確な計算
- さまざまな学生のシナリオにおけるレジストリの機能
- 境界条件とエッジケース
チートシート
このチャレンジでは、適切なカプセル化とバリデーションを備えたオブジェクト指向プログラミングの原則を使用して、完全な学生記録管理システムを実装することに焦点を当てます。
システムは、主に2つのコンポーネントで構成されています。
- Student クラス - 適切なカプセル化を用いて個々の学生データを管理します
- StudentRegistry クラス - 学生のコレクションを管理します
主な実装要件は以下の通りです。
- 適切な属性のバリデーションとエラーハンドリング
- 成績平均の正確な計算
- 複数の学生を管理するためのレジストリ機能
- 境界条件とエッジケースの処理
自分で試してみよう
from student import Student
from studentregistry import StudentRegistry
import time
import random
# 包括的なテストのためのテストケースハンドラー
test_case = input()
if test_case == "default_test":
# 学生を作成
student1 = Student(1001, "Alice Smith")
student2 = Student(1002, "Bob Johnson")
student3 = Student(1003, "Charlie Brown")
# 成績を追加
student1.add_grade("Math", 90)
student1.add_grade("Science", 85)
student1.add_grade("English", 92)
student2.add_grade("Math", 78)
student2.add_grade("Science", 80)
student2.add_grade("English", 85)
student3.add_grade("Math", 95)
student3.add_grade("Science", 91)
student3.add_grade("English", 89)
# 学生の記録を表示
print("Student Records:")
student1.display_record()
print()
student2.display_record()
print()
student3.display_record()
print()
# 名前のバリデーションをテスト
try:
student1.name = "J" # 短すぎる
except ValueError as e:
print(f"Name validation error: {e}")
print()
# レジストリを作成し学生を追加
registry = StudentRegistry()
registry.add_student(student1)
registry.add_student(student2)
registry.add_student(student3)
# すべての学生を表示
print("All Students in Registry:")
registry.display_all()
print()
# 成績優秀者を取得
top_student = registry.get_top_student()
print(f"Top Student: {top_student.name} (Average: {top_student.grade_average})")
# 学生を削除
registry.remove_student(1002) # Bobを削除
print("\
After removing student 1002:")
registry.display_all()
elif test_case == "empty_registry":
# 空のレジストリをテスト
registry = StudentRegistry()
top_student = registry.get_top_student()
if top_student is None:
print("Top student in empty registry: None")
print("Displaying all students in empty registry:")
registry.display_all() # 何も表示されないはず
elif test_case == "validation_tests":
# すべてのバリデーションルールをテスト
student = Student(1001, "Valid Name")
print(f"Created student with name: {student.name}")
# 空の名前をテスト
try:
student.name = ""
except ValueError as e:
print(f"Empty name test: {e}")
# 1文字の名前をテスト
try:
student.name = "A"
except ValueError as e:
print(f"Single character name test: {e}")
# ブール値ではない在籍状況の値をテスト
try:
student.enrolled = "yes"
except ValueError as e:
print(f"Non-boolean enrolled test: {e}")
# 有効な変更をテスト
student.name = "New Valid Name"
student.enrolled = False
print(f"After valid changes - Name: {student.name}, Enrolled: {student.enrolled}")
elif test_case == "grade_calculation":
# 成績平均の計算をテスト
student = Student(1001, "Test Student")
print(f"Student with no grades - Average: {student.grade_average}")
# 成績を1つ追加
student.add_grade("Math", 85)
print(f"Student with one grade - Average: {student.grade_average}")
# さらに成績を追加
student.add_grade("Science", 90)
student.add_grade("English", 95)
print(f"Student with multiple grades - Average: {student.grade_average}")
elif test_case == "registry_operations":
# すべてのレジストリ操作をテスト
registry = StudentRegistry()
# 学生を作成
student1 = Student(101, "Student One")
student2 = Student(102, "Student Two")
# 学生を追加
registry.add_student(student1)
registry.add_student(student2)
print("After adding students:")
registry.display_all()
# 学生を取得
retrieved_student = registry.get_student(101)
print(f"\
Retrieved student 101: {retrieved_student.name if retrieved_student else None}")
# 存在しない学生を取得
non_existent = registry.get_student(999)
print(f"Retrieved student 999: {non_existent}")
# 学生を削除
registry.remove_student(101)
print("\
After removing student 101:")
registry.display_all()
# 存在しない学生を削除(エラーが発生しないこと)
registry.remove_student(999)
print("\
After attempting to remove non-existent student 999:")
registry.display_all()
elif test_case == "large_registry":
# 多数の学生でのパフォーマンスをテスト
start_time = time.time()
registry = StudentRegistry()
# ランダムな成績を持つ100人の学生を作成
for i in range(1, 101):
student = Student(1000 + i, f"Student {i}")
# 5つのランダムな成績を追加
for j in range(5):
student.add_grade(f"Course {j+1}", random.randint(60, 100))
registry.add_student(student)
creation_time = time.time() - start_time
print(f"Time to create 100 students: {creation_time:.4f} seconds")
# 成績優秀者を見つける
start_time = time.time()
top_student = registry.get_top_student()
top_time = time.time() - start_time
print(f"Time to find top student: {top_time:.4f} seconds")
print(f"Top student: {top_student.name} with average {top_student.grade_average:.2f}")
# 上位5名の学生を手動で見つける
print("\
Top 5 students:")
students_list = []
for i in range(1, 101):
student = registry.get_student(1000 + i)
students_list.append(student)
# 成績平均の降順でソート
students_list.sort(key=lambda s: s.grade_average, reverse=True)
# 上位5名を表示
for i in range(5):
student = students_list[i]
print(f"{i+1}. {student.name}: {student.grade_average:.2f}")