فایل نمرات
در این تمرین از شما میخواهیم برنامهای بنویسیم تا بتوانیم با فایل نمرات دانشجویان کار کرده و کارهایی که پیش از این توسط مسئولین آموزش بهصورت دستی انجام میشد را خودکار کنیم. هر سطر از این فایل، دارای سه بخش (ستون) است که با کاراکتر فاصله (" ") از هم جدا شدهاند. این سه بخش بهترتیب عبارتند از:
- شمارهی دانشجویی: عدد صحیح
- کد درس: عدد صحیح
- نمره: عدد اعشاری
یعنی هر سطر از این فایل مشخص میکند که یک دانشجو در یک درس چه نمرهای را گرفتهاست.
📄 کلاس Grade
کلاس Grade در پروژهی اولیه پیادهسازی شده و تنها دارای یک تابع سازنده است. در این تابع بهترتیب شمارهی دانشجویی، کد درس و نمره دریافت میشوند و در شیء ذخیره میشوند.
class Grade:
def __init__(self, stu_id, crc_code, score):
self.student_id = stu_id
self.course_code = crc_code
self.score = score
نام متغیرهای این کلاس را تغییر ندهید.
🛠️ کلاس CourseUtil
این کلاس دارای توابعی میباشد که در ادامه به توضیح آنها پرداختهایم. این کلاس نیازی به تابع سازنده ندارد.
🔹 set_file(self, address)
آدرس فایل نمرات را دریافت میکند. هیچ خروجیای ندارد. فقط یک بار در طول اجرای برنامه فراخوانی میشود. آدرس فایل را در
self.addressذخیره کنید.
🔹 load(self, line_number)
شمارهی یک خط را دریافت میکند (شمارش از ۱ شروع میشود) و اطلاعات آن خط را در قالب شیئی از کلاس
Gradeبرمیگرداند. اگر شماره خط بزرگتر از تعداد خطهای فایل بود،Noneبرگرداند.
🔹 calc_course_average(self, course_code)
کد یک درس را دریافت میکند و میانگین نمرههای مربوط به آن درس را بهصورت
floatبرمیگرداند. تضمین میشود که کد درس ورودی در فایل نمرات موجود است.
🔹 calc_student_average(self, student_id)
شمارهی دانشجویی را دریافت میکند و میانگین نمرههای آن دانشجو را بهصورت
floatبرمیگرداند. تضمین میشود که شمارهی دانشجویی در فایل نمرات موجود است.
🔹 count(self)
تعداد کل نمراتی را که درون فایل وجود دارد، بهصورت
intبرگرداند.
🔹 save(self, grade)
شیء
Gradeرا دریافت میکند و اطلاعات آن را در انتهای فایل نمرات ذخیره میکند. اگر برای دانشجو و درسی که نمرهاش در فایل وجود دارد، نمرهی جدیدی ثبت شود، نباید در فایل تغییری ایجاد شود.
- شمارهی دانشجویی، کد درس و نمره باید بهصورت عددی در شیء
Gradeذخیره شوند.- در انتهای فایل
\nوجود ندارد. شما نیز باید طوری فایل را تغییر دهید که هیچگاه در انتهای فایل\nوجود نداشته باشد.- در تابع
loadمیتوانید فایل را باز کنید و اطلاعات را در شیء ذخیره کنید. اگر اطلاعات را در شیء ذخیره میکنید، در هنگام افزودن اطلاعات به فایل، باید اطلاعات ذخیرهشده در شیء را نیز بهروزرسانی کنید.
📖 مثال
util = CourseUtil()
util.set_file(file)
print(util.count())
grade = Grade(445612, 1234, 12)
util.save(grade)
print(util.count())
util.set_file(file)
print(util.count())
📤 خروجی
2
3
3
✅ پاسخ نهایی
class CourseUtil:
def set_file(self, address):
self.address = address
def _grades(self):
try:
with open(self.address) as handle:
lines = handle.read().split("\n")
except FileNotFoundError:
return []
grades = []
for line in lines:
parts = line.split()
if len(parts) == 3:
grades.append(Grade(int(parts[0]), int(parts[1]), float(parts[2])))
return grades
def load(self, line_number):
grades = self._grades()
if 1 <= line_number <= len(grades):
return grades[line_number - 1]
return None
def calc_course_average(self, course_code):
scores = [g.score for g in self._grades() if g.course_code == course_code]
return sum(scores) / len(scores)
def calc_student_average(self, student_id):
scores = [g.score for g in self._grades() if g.student_id == student_id]
return sum(scores) / len(scores)
def count(self):
return len(self._grades())
def save(self, grade):
grades = self._grades()
if any(g.student_id == grade.student_id and g.course_code == grade.course_code for g in grades):
return
with open(self.address) as handle:
text = handle.read().rstrip("\n")
line = f"{grade.student_id} {grade.course_code} {grade.score}"
with open(self.address, "w") as handle:
handle.write(line if not text else text + "\n" + line)
📄 main.py
📖 توضیح کد
- توابع کمکی:
_read_all_lines: تمام خطوط فایل را میخواند_write_all_lines: خطوط را در فایل مینویسد (بدون\nاضافی در انتها)_parse_line: یک خط را به شیءGradeتبدیل میکند_line_from_grade: شیءGradeرا به خط تبدیل میکند - تابع
load: خط مورد نظر را خوانده و بهGradeتبدیل میکند - تابع
calc_course_average: میانگین نمرات یک درس را محاسبه میکند - تابع
calc_student_average: میانگین نمرات یک دانشجو را محاسبه میکند - تابع
count: تعداد نمرات موجود در فایل را برمیگرداند - تابع
save: ابتدا بررسی میکند که نمره تکراری نباشد، سپس آن را به فایل اضافه میکند
در تابع
save، اگر نمرهای تکراری باشد (همان دانشجو و همان درس)، هیچ تغییری در فایل ایجاد نمیشود.همچنین در انتهای فایل هرگز
\nوجود ندارد.
🚀 پس از تکمیل کلاس، میتوانید آن را با فایلهای مختلف تست کنید و از صحت عملکرد آن اطمینان حاصل کنید.
نمونهها
make_file("grades.txt", "445611 1234 18.5\n445612 1235 12")
util = CourseUtil()
util.set_file("grades.txt")
util.count()
util.save(Grade(445612, 1234, 12))
util.count()
util.set_file("grades.txt")
util.count()
open("grades.txt").read()2 3 3 '445611 1234 18.5\n445612 1235 12\n445612 1234 12'
make_file("grades.txt", "445611 1234 18.5\n445612 1235 12")
util = CourseUtil()
util.set_file("grades.txt")
g = util.load(2)
[g.student_id, g.course_code, g.score]
[type(g.student_id).__name__, type(g.course_code).__name__, type(g.score).__name__]
util.load(3) is None[445612, 1235, 12.0] ['int', 'int', 'float'] True
make_file("grades.txt", "1 10 20\n2 10 15\n1 20 11\n3 10 16\n2 20 19.5")
util = CourseUtil()
util.set_file("grades.txt")
util.calc_course_average(10)
util.calc_course_average(20)
util.calc_student_average(1)
util.calc_student_average(2)
type(util.calc_course_average(10)).__name__17.0 15.25 15.5 17.25 'float'
make_file("grades.txt", "445611 1234 18.5\n445612 1235 12")
util = CourseUtil()
util.set_file("grades.txt")
util.save(Grade(445611, 1234, 20))
util.count()
open("grades.txt").read()2 '445611 1234 18.5\n445612 1235 12'
make_file("grades.txt", "7 1 10")
util = CourseUtil()
util.set_file("grades.txt")
util.save(Grade(8, 1, 12.75))
util.save(Grade(9, 2, 19))
[util.count(), util.calc_course_average(1)]
open("grades.txt").read()[3, 11.375] '7 1 10\n8 1 12.75\n9 2 19'
برای نوشتن پاسخ و دریافت امتیاز، ابتدا وارد حساب شوید.
ورود