راه
۴ کیو· سختپیشرفتهPYTHON۴ ثانیه · ۲۵۶ مگابایت

فایل نمرات

در این تمرین از شما می‌خواهیم برنامه‌ای بنویسیم تا بتوانیم با فایل نمرات دانشجویان کار کرده و کارهایی که پیش از این توسط مسئولین آموزش به‌صورت دستی انجام می‌شد را خودکار کنیم. هر سطر از این فایل، دارای سه بخش (ستون) است که با کاراکتر فاصله (" ") از هم جدا شده‌اند. این سه بخش به‌ترتیب عبارتند از:

  • شماره‌ی دانشجویی: عدد صحیح
  • کد درس: عدد صحیح
  • نمره: عدد اعشاری

یعنی هر سطر از این فایل مشخص می‌کند که یک دانشجو در یک درس چه نمره‌ای را گرفته‌است.


📄 کلاس Grade

کلاس Grade در پروژه‌ی اولیه پیاده‌سازی شده و تنها دارای یک تابع سازنده است. در این تابع به‌ترتیب شماره‌ی دانشجویی، کد درس و نمره دریافت می‌شوند و در شیء ذخیره می‌شوند.

python
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 می‌توانید فایل را باز کنید و اطلاعات را در شیء ذخیره کنید. اگر اطلاعات را در شیء ذخیره می‌کنید، در هنگام افزودن اطلاعات به فایل، باید اطلاعات ذخیره‌شده در شیء را نیز به‌روزرسانی کنید.

📖 مثال

python
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())

📤 خروجی

python
2
3
3

✅ پاسخ نهایی

python
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'

برای نوشتن پاسخ و دریافت امتیاز، ابتدا وارد حساب شوید.

ورود