Program to compute final grade for weighted assignments

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
4
down vote

favorite












I wrote a "gradebook" program. This takes in grades for various assignments. The assignments types are weighted differently and final grade is computed at the end. The code works but I can't help but think I am being ham handed in my approach. Should I be using a dictionary instead of storing things like hw_final, lab_final, and exam_final as global variables?



hw_tally = 0
hw_weight_count = 0
hw_final = 0
lab_tally = 0
lab_weight_count = 0
lab_final = 0
exam_tally = 0
exam_weight_count = 0
exam_final = 0


def assignment(kind, grade, weight=1):
global hw_tally, hw_weight_count, hw_final, lab_tally, lab_weight_count, lab_final, exam_tally, exam_weight_count, exam_final
if kind == 'hw':
hw_weight_count += weight
hw_temporary = (grade * weight)
hw_tally += hw_temporary
hw_final = hw_tally/hw_weight_count
elif kind == 'lab':
lab_weight_count += weight
lab_temporary = (grade * weight)
lab_tally += lab_temporary
lab_final = lab_tally/lab_weight_count
elif kind == 'exam':
exam_weight_count += weight
exam_temporary = (grade * weight)
exam_tally += exam_temporary
exam_final = exam_tally/exam_weight_count


assignment('hw', 81)
assignment('exam', 90, 4)
assignment('hw', 100, 2)
assignment('lab', 84, 3)
assignment('lab', 90, 2)
assignment('exam', 78)
assignment('exam', 85)
assignment('lab', 88)
assignment('exam', 75)

hw_weight_percent = 0.4
lab_weight_percent = 0.1
exam_weight_percent = 0.5

final_grade = ((hw_final * hw_weight_percent) + (lab_final *
lab_weight_percent) + (exam_final * exam_weight_percent))
print ("Final grade = ", final_grade)






share|improve this question

















  • 1




    @depperm Comments are for seeking clarification to the question, and may be deleted. Please put all suggestions for in answers, even if they are brief.
    – 200_success
    May 1 at 16:25
















up vote
4
down vote

favorite












I wrote a "gradebook" program. This takes in grades for various assignments. The assignments types are weighted differently and final grade is computed at the end. The code works but I can't help but think I am being ham handed in my approach. Should I be using a dictionary instead of storing things like hw_final, lab_final, and exam_final as global variables?



hw_tally = 0
hw_weight_count = 0
hw_final = 0
lab_tally = 0
lab_weight_count = 0
lab_final = 0
exam_tally = 0
exam_weight_count = 0
exam_final = 0


def assignment(kind, grade, weight=1):
global hw_tally, hw_weight_count, hw_final, lab_tally, lab_weight_count, lab_final, exam_tally, exam_weight_count, exam_final
if kind == 'hw':
hw_weight_count += weight
hw_temporary = (grade * weight)
hw_tally += hw_temporary
hw_final = hw_tally/hw_weight_count
elif kind == 'lab':
lab_weight_count += weight
lab_temporary = (grade * weight)
lab_tally += lab_temporary
lab_final = lab_tally/lab_weight_count
elif kind == 'exam':
exam_weight_count += weight
exam_temporary = (grade * weight)
exam_tally += exam_temporary
exam_final = exam_tally/exam_weight_count


assignment('hw', 81)
assignment('exam', 90, 4)
assignment('hw', 100, 2)
assignment('lab', 84, 3)
assignment('lab', 90, 2)
assignment('exam', 78)
assignment('exam', 85)
assignment('lab', 88)
assignment('exam', 75)

hw_weight_percent = 0.4
lab_weight_percent = 0.1
exam_weight_percent = 0.5

final_grade = ((hw_final * hw_weight_percent) + (lab_final *
lab_weight_percent) + (exam_final * exam_weight_percent))
print ("Final grade = ", final_grade)






share|improve this question

















  • 1




    @depperm Comments are for seeking clarification to the question, and may be deleted. Please put all suggestions for in answers, even if they are brief.
    – 200_success
    May 1 at 16:25












up vote
4
down vote

favorite









up vote
4
down vote

favorite











I wrote a "gradebook" program. This takes in grades for various assignments. The assignments types are weighted differently and final grade is computed at the end. The code works but I can't help but think I am being ham handed in my approach. Should I be using a dictionary instead of storing things like hw_final, lab_final, and exam_final as global variables?



hw_tally = 0
hw_weight_count = 0
hw_final = 0
lab_tally = 0
lab_weight_count = 0
lab_final = 0
exam_tally = 0
exam_weight_count = 0
exam_final = 0


def assignment(kind, grade, weight=1):
global hw_tally, hw_weight_count, hw_final, lab_tally, lab_weight_count, lab_final, exam_tally, exam_weight_count, exam_final
if kind == 'hw':
hw_weight_count += weight
hw_temporary = (grade * weight)
hw_tally += hw_temporary
hw_final = hw_tally/hw_weight_count
elif kind == 'lab':
lab_weight_count += weight
lab_temporary = (grade * weight)
lab_tally += lab_temporary
lab_final = lab_tally/lab_weight_count
elif kind == 'exam':
exam_weight_count += weight
exam_temporary = (grade * weight)
exam_tally += exam_temporary
exam_final = exam_tally/exam_weight_count


assignment('hw', 81)
assignment('exam', 90, 4)
assignment('hw', 100, 2)
assignment('lab', 84, 3)
assignment('lab', 90, 2)
assignment('exam', 78)
assignment('exam', 85)
assignment('lab', 88)
assignment('exam', 75)

hw_weight_percent = 0.4
lab_weight_percent = 0.1
exam_weight_percent = 0.5

final_grade = ((hw_final * hw_weight_percent) + (lab_final *
lab_weight_percent) + (exam_final * exam_weight_percent))
print ("Final grade = ", final_grade)






share|improve this question













I wrote a "gradebook" program. This takes in grades for various assignments. The assignments types are weighted differently and final grade is computed at the end. The code works but I can't help but think I am being ham handed in my approach. Should I be using a dictionary instead of storing things like hw_final, lab_final, and exam_final as global variables?



hw_tally = 0
hw_weight_count = 0
hw_final = 0
lab_tally = 0
lab_weight_count = 0
lab_final = 0
exam_tally = 0
exam_weight_count = 0
exam_final = 0


def assignment(kind, grade, weight=1):
global hw_tally, hw_weight_count, hw_final, lab_tally, lab_weight_count, lab_final, exam_tally, exam_weight_count, exam_final
if kind == 'hw':
hw_weight_count += weight
hw_temporary = (grade * weight)
hw_tally += hw_temporary
hw_final = hw_tally/hw_weight_count
elif kind == 'lab':
lab_weight_count += weight
lab_temporary = (grade * weight)
lab_tally += lab_temporary
lab_final = lab_tally/lab_weight_count
elif kind == 'exam':
exam_weight_count += weight
exam_temporary = (grade * weight)
exam_tally += exam_temporary
exam_final = exam_tally/exam_weight_count


assignment('hw', 81)
assignment('exam', 90, 4)
assignment('hw', 100, 2)
assignment('lab', 84, 3)
assignment('lab', 90, 2)
assignment('exam', 78)
assignment('exam', 85)
assignment('lab', 88)
assignment('exam', 75)

hw_weight_percent = 0.4
lab_weight_percent = 0.1
exam_weight_percent = 0.5

final_grade = ((hw_final * hw_weight_percent) + (lab_final *
lab_weight_percent) + (exam_final * exam_weight_percent))
print ("Final grade = ", final_grade)








share|improve this question












share|improve this question




share|improve this question








edited May 1 at 16:24









200_success

123k14142399




123k14142399









asked May 1 at 14:21









Erich Purpur

262




262







  • 1




    @depperm Comments are for seeking clarification to the question, and may be deleted. Please put all suggestions for in answers, even if they are brief.
    – 200_success
    May 1 at 16:25












  • 1




    @depperm Comments are for seeking clarification to the question, and may be deleted. Please put all suggestions for in answers, even if they are brief.
    – 200_success
    May 1 at 16:25







1




1




@depperm Comments are for seeking clarification to the question, and may be deleted. Please put all suggestions for in answers, even if they are brief.
– 200_success
May 1 at 16:25




@depperm Comments are for seeking clarification to the question, and may be deleted. Please put all suggestions for in answers, even if they are brief.
– 200_success
May 1 at 16:25










2 Answers
2






active

oldest

votes

















up vote
3
down vote














  1. Split assignment into three functions. homework, exam and labwork. Take:



    def homework(grade, weight=1):
    global hw_tally, hw_weight_count, hw_final
    hw_weight_count += weight
    hw_temporary = (grade * weight)
    hw_tally += hw_temporary
    hw_final = hw_tally/hw_weight_count



  2. Change homework into a class.



    class Scores:
    def __init__(self):
    self.tally = 0
    self.weight_count = 0

    @property
    def final(self):
    return self.tally / self.weight_count

    def grade(grade, weight=1):
    self.weight_count += weight
    self.tally += grade * weight


    Now you can use the above class to total all the separate things. And then perform your total on Scores.final.



  3. Group the exam types into another class, say StudentScores.


  4. Expand Scores to also take the percentage. And make final return the percentage.

  5. Move your final calculation into StudentScores.

This can make:



class Scores:
def __init__(self, percentage=1):
self.tally = 0
self.weight_count = 0
self.percentage = percentage

@property
def final(self):
return self.tally / self.weight_count * self.percentage

def grade(self, grade, weight=1):
self.weight_count += weight
self.tally += grade * weight


class StudentScores:
def __init__(self, scores):
total = sum(scores.values())
self._scores =
key: Scores(score / total)
for key, score in scores.items()


def __getattr__(self, name):
return self._scores[name]

@property
def grade(self):
return sum(scores.final for scores in self._scores.values())


student = StudentScores(
'homework': 0.4,
'labwork': 0.1,
'exam': 0.5
)

student.homework.grade(81)
student.exam.grade(90, 4)
student.homework.grade(100, 2)
student.labwork.grade(84, 3)
student.labwork.grade(90, 2)
student.exam.grade(78)
student.exam.grade(85)
student.labwork.grade(88)
student.exam.grade(75)

print("Final grade = ", student.grade)



This uses a lot of classes, and isn't really the best way if you're taking data from a file. And so if you store your results as a JSON file, and read it into Python however you want. Then you can default the weights into the JSON data. And then perform the rest of the code in a couple of comprehensions, wrapped in a sum:



results = 
'homework': [
0.4,
[
[81],
[100, 2]
]
],
'labwork': [
0.1,
[
[84, 3],
[90, 2],
[88]
]
],
'exam': [
0.5,
[
[90, 4],
[78],
[85],
[75]
]
]


def default_weights(results):
return [
[percentage, [(score + [1])[:2] for score in scores]]
for percentage, scores in results.values()
]

def grade(results):
return sum(
percentage * sum(s*w for s, w in scores) / sum(w for _, w in scores)
for percentage, scores in results
)

print("Final grade = ", grade(default_weights(results)))





share|improve this answer




























    up vote
    1
    down vote













    Yes it would be better to use a dictionary, that would reduce the amount of global variables. Also you do not need to store and calculated the ..._final all the times, you can calculate it only when you need need it. The (nested) dictionary to store the grades could be:



    scores = 
    "hw" : "tally" : 0, "weight_count" : 0 ,
    "lab" : "tally" : 0, "weight_count" : 0 ,
    "exam" : "tally" : 0, "weight_count" : 0 ,



    Then the assignment function can be made shorter, without calculating the final at this moment:



    def assignment(kind, grade, weight=1):
    global scores
    scores[kind]["weight_count"] += weight
    scores[kind]["tally"] += grade * weight


    We could write another function to calculate the final of a kind:



    def final_of_kind(kind):
    global scores
    return scores[kind]["tally"] / scores[kind]["weight_count"]


    And the rest of the program is almost the same:



    assignment('hw', 81)
    assignment('exam', 90, 4)
    assignment('hw', 100, 2)
    assignment('lab', 84, 3)
    assignment('lab', 90, 2)
    assignment('exam', 78)
    assignment('exam', 85)
    assignment('lab', 88)
    assignment('exam', 75)

    hw_weight_percent = 0.4
    lab_weight_percent = 0.1
    exam_weight_percent = 0.5

    final_grade = ( (final_of_kind("hw") * hw_weight_percent)
    + (final_of_kind("lab") * lab_weight_percent)
    + (final_of_kind("exam") * exam_weight_percent))

    print ("Final grade = ", final_grade)


    Note: the alignment in the assignment of final_grade is frowned up on sometimes, because it is not according to PEP8, but I use it for readability.






    share|improve this answer





















    • thanks Jan. I like your solution more it is easier for me to follow. The above solution is beyond my level of experience
      – Erich Purpur
      May 2 at 15:31










    Your Answer




    StackExchange.ifUsing("editor", function ()
    return StackExchange.using("mathjaxEditing", function ()
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    );
    );
    , "mathjax-editing");

    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "196"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );








     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f193354%2fprogram-to-compute-final-grade-for-weighted-assignments%23new-answer', 'question_page');

    );

    Post as a guest






























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    3
    down vote














    1. Split assignment into three functions. homework, exam and labwork. Take:



      def homework(grade, weight=1):
      global hw_tally, hw_weight_count, hw_final
      hw_weight_count += weight
      hw_temporary = (grade * weight)
      hw_tally += hw_temporary
      hw_final = hw_tally/hw_weight_count



    2. Change homework into a class.



      class Scores:
      def __init__(self):
      self.tally = 0
      self.weight_count = 0

      @property
      def final(self):
      return self.tally / self.weight_count

      def grade(grade, weight=1):
      self.weight_count += weight
      self.tally += grade * weight


      Now you can use the above class to total all the separate things. And then perform your total on Scores.final.



    3. Group the exam types into another class, say StudentScores.


    4. Expand Scores to also take the percentage. And make final return the percentage.

    5. Move your final calculation into StudentScores.

    This can make:



    class Scores:
    def __init__(self, percentage=1):
    self.tally = 0
    self.weight_count = 0
    self.percentage = percentage

    @property
    def final(self):
    return self.tally / self.weight_count * self.percentage

    def grade(self, grade, weight=1):
    self.weight_count += weight
    self.tally += grade * weight


    class StudentScores:
    def __init__(self, scores):
    total = sum(scores.values())
    self._scores =
    key: Scores(score / total)
    for key, score in scores.items()


    def __getattr__(self, name):
    return self._scores[name]

    @property
    def grade(self):
    return sum(scores.final for scores in self._scores.values())


    student = StudentScores(
    'homework': 0.4,
    'labwork': 0.1,
    'exam': 0.5
    )

    student.homework.grade(81)
    student.exam.grade(90, 4)
    student.homework.grade(100, 2)
    student.labwork.grade(84, 3)
    student.labwork.grade(90, 2)
    student.exam.grade(78)
    student.exam.grade(85)
    student.labwork.grade(88)
    student.exam.grade(75)

    print("Final grade = ", student.grade)



    This uses a lot of classes, and isn't really the best way if you're taking data from a file. And so if you store your results as a JSON file, and read it into Python however you want. Then you can default the weights into the JSON data. And then perform the rest of the code in a couple of comprehensions, wrapped in a sum:



    results = 
    'homework': [
    0.4,
    [
    [81],
    [100, 2]
    ]
    ],
    'labwork': [
    0.1,
    [
    [84, 3],
    [90, 2],
    [88]
    ]
    ],
    'exam': [
    0.5,
    [
    [90, 4],
    [78],
    [85],
    [75]
    ]
    ]


    def default_weights(results):
    return [
    [percentage, [(score + [1])[:2] for score in scores]]
    for percentage, scores in results.values()
    ]

    def grade(results):
    return sum(
    percentage * sum(s*w for s, w in scores) / sum(w for _, w in scores)
    for percentage, scores in results
    )

    print("Final grade = ", grade(default_weights(results)))





    share|improve this answer

























      up vote
      3
      down vote














      1. Split assignment into three functions. homework, exam and labwork. Take:



        def homework(grade, weight=1):
        global hw_tally, hw_weight_count, hw_final
        hw_weight_count += weight
        hw_temporary = (grade * weight)
        hw_tally += hw_temporary
        hw_final = hw_tally/hw_weight_count



      2. Change homework into a class.



        class Scores:
        def __init__(self):
        self.tally = 0
        self.weight_count = 0

        @property
        def final(self):
        return self.tally / self.weight_count

        def grade(grade, weight=1):
        self.weight_count += weight
        self.tally += grade * weight


        Now you can use the above class to total all the separate things. And then perform your total on Scores.final.



      3. Group the exam types into another class, say StudentScores.


      4. Expand Scores to also take the percentage. And make final return the percentage.

      5. Move your final calculation into StudentScores.

      This can make:



      class Scores:
      def __init__(self, percentage=1):
      self.tally = 0
      self.weight_count = 0
      self.percentage = percentage

      @property
      def final(self):
      return self.tally / self.weight_count * self.percentage

      def grade(self, grade, weight=1):
      self.weight_count += weight
      self.tally += grade * weight


      class StudentScores:
      def __init__(self, scores):
      total = sum(scores.values())
      self._scores =
      key: Scores(score / total)
      for key, score in scores.items()


      def __getattr__(self, name):
      return self._scores[name]

      @property
      def grade(self):
      return sum(scores.final for scores in self._scores.values())


      student = StudentScores(
      'homework': 0.4,
      'labwork': 0.1,
      'exam': 0.5
      )

      student.homework.grade(81)
      student.exam.grade(90, 4)
      student.homework.grade(100, 2)
      student.labwork.grade(84, 3)
      student.labwork.grade(90, 2)
      student.exam.grade(78)
      student.exam.grade(85)
      student.labwork.grade(88)
      student.exam.grade(75)

      print("Final grade = ", student.grade)



      This uses a lot of classes, and isn't really the best way if you're taking data from a file. And so if you store your results as a JSON file, and read it into Python however you want. Then you can default the weights into the JSON data. And then perform the rest of the code in a couple of comprehensions, wrapped in a sum:



      results = 
      'homework': [
      0.4,
      [
      [81],
      [100, 2]
      ]
      ],
      'labwork': [
      0.1,
      [
      [84, 3],
      [90, 2],
      [88]
      ]
      ],
      'exam': [
      0.5,
      [
      [90, 4],
      [78],
      [85],
      [75]
      ]
      ]


      def default_weights(results):
      return [
      [percentage, [(score + [1])[:2] for score in scores]]
      for percentage, scores in results.values()
      ]

      def grade(results):
      return sum(
      percentage * sum(s*w for s, w in scores) / sum(w for _, w in scores)
      for percentage, scores in results
      )

      print("Final grade = ", grade(default_weights(results)))





      share|improve this answer























        up vote
        3
        down vote










        up vote
        3
        down vote










        1. Split assignment into three functions. homework, exam and labwork. Take:



          def homework(grade, weight=1):
          global hw_tally, hw_weight_count, hw_final
          hw_weight_count += weight
          hw_temporary = (grade * weight)
          hw_tally += hw_temporary
          hw_final = hw_tally/hw_weight_count



        2. Change homework into a class.



          class Scores:
          def __init__(self):
          self.tally = 0
          self.weight_count = 0

          @property
          def final(self):
          return self.tally / self.weight_count

          def grade(grade, weight=1):
          self.weight_count += weight
          self.tally += grade * weight


          Now you can use the above class to total all the separate things. And then perform your total on Scores.final.



        3. Group the exam types into another class, say StudentScores.


        4. Expand Scores to also take the percentage. And make final return the percentage.

        5. Move your final calculation into StudentScores.

        This can make:



        class Scores:
        def __init__(self, percentage=1):
        self.tally = 0
        self.weight_count = 0
        self.percentage = percentage

        @property
        def final(self):
        return self.tally / self.weight_count * self.percentage

        def grade(self, grade, weight=1):
        self.weight_count += weight
        self.tally += grade * weight


        class StudentScores:
        def __init__(self, scores):
        total = sum(scores.values())
        self._scores =
        key: Scores(score / total)
        for key, score in scores.items()


        def __getattr__(self, name):
        return self._scores[name]

        @property
        def grade(self):
        return sum(scores.final for scores in self._scores.values())


        student = StudentScores(
        'homework': 0.4,
        'labwork': 0.1,
        'exam': 0.5
        )

        student.homework.grade(81)
        student.exam.grade(90, 4)
        student.homework.grade(100, 2)
        student.labwork.grade(84, 3)
        student.labwork.grade(90, 2)
        student.exam.grade(78)
        student.exam.grade(85)
        student.labwork.grade(88)
        student.exam.grade(75)

        print("Final grade = ", student.grade)



        This uses a lot of classes, and isn't really the best way if you're taking data from a file. And so if you store your results as a JSON file, and read it into Python however you want. Then you can default the weights into the JSON data. And then perform the rest of the code in a couple of comprehensions, wrapped in a sum:



        results = 
        'homework': [
        0.4,
        [
        [81],
        [100, 2]
        ]
        ],
        'labwork': [
        0.1,
        [
        [84, 3],
        [90, 2],
        [88]
        ]
        ],
        'exam': [
        0.5,
        [
        [90, 4],
        [78],
        [85],
        [75]
        ]
        ]


        def default_weights(results):
        return [
        [percentage, [(score + [1])[:2] for score in scores]]
        for percentage, scores in results.values()
        ]

        def grade(results):
        return sum(
        percentage * sum(s*w for s, w in scores) / sum(w for _, w in scores)
        for percentage, scores in results
        )

        print("Final grade = ", grade(default_weights(results)))





        share|improve this answer














        1. Split assignment into three functions. homework, exam and labwork. Take:



          def homework(grade, weight=1):
          global hw_tally, hw_weight_count, hw_final
          hw_weight_count += weight
          hw_temporary = (grade * weight)
          hw_tally += hw_temporary
          hw_final = hw_tally/hw_weight_count



        2. Change homework into a class.



          class Scores:
          def __init__(self):
          self.tally = 0
          self.weight_count = 0

          @property
          def final(self):
          return self.tally / self.weight_count

          def grade(grade, weight=1):
          self.weight_count += weight
          self.tally += grade * weight


          Now you can use the above class to total all the separate things. And then perform your total on Scores.final.



        3. Group the exam types into another class, say StudentScores.


        4. Expand Scores to also take the percentage. And make final return the percentage.

        5. Move your final calculation into StudentScores.

        This can make:



        class Scores:
        def __init__(self, percentage=1):
        self.tally = 0
        self.weight_count = 0
        self.percentage = percentage

        @property
        def final(self):
        return self.tally / self.weight_count * self.percentage

        def grade(self, grade, weight=1):
        self.weight_count += weight
        self.tally += grade * weight


        class StudentScores:
        def __init__(self, scores):
        total = sum(scores.values())
        self._scores =
        key: Scores(score / total)
        for key, score in scores.items()


        def __getattr__(self, name):
        return self._scores[name]

        @property
        def grade(self):
        return sum(scores.final for scores in self._scores.values())


        student = StudentScores(
        'homework': 0.4,
        'labwork': 0.1,
        'exam': 0.5
        )

        student.homework.grade(81)
        student.exam.grade(90, 4)
        student.homework.grade(100, 2)
        student.labwork.grade(84, 3)
        student.labwork.grade(90, 2)
        student.exam.grade(78)
        student.exam.grade(85)
        student.labwork.grade(88)
        student.exam.grade(75)

        print("Final grade = ", student.grade)



        This uses a lot of classes, and isn't really the best way if you're taking data from a file. And so if you store your results as a JSON file, and read it into Python however you want. Then you can default the weights into the JSON data. And then perform the rest of the code in a couple of comprehensions, wrapped in a sum:



        results = 
        'homework': [
        0.4,
        [
        [81],
        [100, 2]
        ]
        ],
        'labwork': [
        0.1,
        [
        [84, 3],
        [90, 2],
        [88]
        ]
        ],
        'exam': [
        0.5,
        [
        [90, 4],
        [78],
        [85],
        [75]
        ]
        ]


        def default_weights(results):
        return [
        [percentage, [(score + [1])[:2] for score in scores]]
        for percentage, scores in results.values()
        ]

        def grade(results):
        return sum(
        percentage * sum(s*w for s, w in scores) / sum(w for _, w in scores)
        for percentage, scores in results
        )

        print("Final grade = ", grade(default_weights(results)))






        share|improve this answer













        share|improve this answer



        share|improve this answer











        answered May 1 at 15:19









        Peilonrayz

        24.3k336102




        24.3k336102






















            up vote
            1
            down vote













            Yes it would be better to use a dictionary, that would reduce the amount of global variables. Also you do not need to store and calculated the ..._final all the times, you can calculate it only when you need need it. The (nested) dictionary to store the grades could be:



            scores = 
            "hw" : "tally" : 0, "weight_count" : 0 ,
            "lab" : "tally" : 0, "weight_count" : 0 ,
            "exam" : "tally" : 0, "weight_count" : 0 ,



            Then the assignment function can be made shorter, without calculating the final at this moment:



            def assignment(kind, grade, weight=1):
            global scores
            scores[kind]["weight_count"] += weight
            scores[kind]["tally"] += grade * weight


            We could write another function to calculate the final of a kind:



            def final_of_kind(kind):
            global scores
            return scores[kind]["tally"] / scores[kind]["weight_count"]


            And the rest of the program is almost the same:



            assignment('hw', 81)
            assignment('exam', 90, 4)
            assignment('hw', 100, 2)
            assignment('lab', 84, 3)
            assignment('lab', 90, 2)
            assignment('exam', 78)
            assignment('exam', 85)
            assignment('lab', 88)
            assignment('exam', 75)

            hw_weight_percent = 0.4
            lab_weight_percent = 0.1
            exam_weight_percent = 0.5

            final_grade = ( (final_of_kind("hw") * hw_weight_percent)
            + (final_of_kind("lab") * lab_weight_percent)
            + (final_of_kind("exam") * exam_weight_percent))

            print ("Final grade = ", final_grade)


            Note: the alignment in the assignment of final_grade is frowned up on sometimes, because it is not according to PEP8, but I use it for readability.






            share|improve this answer





















            • thanks Jan. I like your solution more it is easier for me to follow. The above solution is beyond my level of experience
              – Erich Purpur
              May 2 at 15:31














            up vote
            1
            down vote













            Yes it would be better to use a dictionary, that would reduce the amount of global variables. Also you do not need to store and calculated the ..._final all the times, you can calculate it only when you need need it. The (nested) dictionary to store the grades could be:



            scores = 
            "hw" : "tally" : 0, "weight_count" : 0 ,
            "lab" : "tally" : 0, "weight_count" : 0 ,
            "exam" : "tally" : 0, "weight_count" : 0 ,



            Then the assignment function can be made shorter, without calculating the final at this moment:



            def assignment(kind, grade, weight=1):
            global scores
            scores[kind]["weight_count"] += weight
            scores[kind]["tally"] += grade * weight


            We could write another function to calculate the final of a kind:



            def final_of_kind(kind):
            global scores
            return scores[kind]["tally"] / scores[kind]["weight_count"]


            And the rest of the program is almost the same:



            assignment('hw', 81)
            assignment('exam', 90, 4)
            assignment('hw', 100, 2)
            assignment('lab', 84, 3)
            assignment('lab', 90, 2)
            assignment('exam', 78)
            assignment('exam', 85)
            assignment('lab', 88)
            assignment('exam', 75)

            hw_weight_percent = 0.4
            lab_weight_percent = 0.1
            exam_weight_percent = 0.5

            final_grade = ( (final_of_kind("hw") * hw_weight_percent)
            + (final_of_kind("lab") * lab_weight_percent)
            + (final_of_kind("exam") * exam_weight_percent))

            print ("Final grade = ", final_grade)


            Note: the alignment in the assignment of final_grade is frowned up on sometimes, because it is not according to PEP8, but I use it for readability.






            share|improve this answer





















            • thanks Jan. I like your solution more it is easier for me to follow. The above solution is beyond my level of experience
              – Erich Purpur
              May 2 at 15:31












            up vote
            1
            down vote










            up vote
            1
            down vote









            Yes it would be better to use a dictionary, that would reduce the amount of global variables. Also you do not need to store and calculated the ..._final all the times, you can calculate it only when you need need it. The (nested) dictionary to store the grades could be:



            scores = 
            "hw" : "tally" : 0, "weight_count" : 0 ,
            "lab" : "tally" : 0, "weight_count" : 0 ,
            "exam" : "tally" : 0, "weight_count" : 0 ,



            Then the assignment function can be made shorter, without calculating the final at this moment:



            def assignment(kind, grade, weight=1):
            global scores
            scores[kind]["weight_count"] += weight
            scores[kind]["tally"] += grade * weight


            We could write another function to calculate the final of a kind:



            def final_of_kind(kind):
            global scores
            return scores[kind]["tally"] / scores[kind]["weight_count"]


            And the rest of the program is almost the same:



            assignment('hw', 81)
            assignment('exam', 90, 4)
            assignment('hw', 100, 2)
            assignment('lab', 84, 3)
            assignment('lab', 90, 2)
            assignment('exam', 78)
            assignment('exam', 85)
            assignment('lab', 88)
            assignment('exam', 75)

            hw_weight_percent = 0.4
            lab_weight_percent = 0.1
            exam_weight_percent = 0.5

            final_grade = ( (final_of_kind("hw") * hw_weight_percent)
            + (final_of_kind("lab") * lab_weight_percent)
            + (final_of_kind("exam") * exam_weight_percent))

            print ("Final grade = ", final_grade)


            Note: the alignment in the assignment of final_grade is frowned up on sometimes, because it is not according to PEP8, but I use it for readability.






            share|improve this answer













            Yes it would be better to use a dictionary, that would reduce the amount of global variables. Also you do not need to store and calculated the ..._final all the times, you can calculate it only when you need need it. The (nested) dictionary to store the grades could be:



            scores = 
            "hw" : "tally" : 0, "weight_count" : 0 ,
            "lab" : "tally" : 0, "weight_count" : 0 ,
            "exam" : "tally" : 0, "weight_count" : 0 ,



            Then the assignment function can be made shorter, without calculating the final at this moment:



            def assignment(kind, grade, weight=1):
            global scores
            scores[kind]["weight_count"] += weight
            scores[kind]["tally"] += grade * weight


            We could write another function to calculate the final of a kind:



            def final_of_kind(kind):
            global scores
            return scores[kind]["tally"] / scores[kind]["weight_count"]


            And the rest of the program is almost the same:



            assignment('hw', 81)
            assignment('exam', 90, 4)
            assignment('hw', 100, 2)
            assignment('lab', 84, 3)
            assignment('lab', 90, 2)
            assignment('exam', 78)
            assignment('exam', 85)
            assignment('lab', 88)
            assignment('exam', 75)

            hw_weight_percent = 0.4
            lab_weight_percent = 0.1
            exam_weight_percent = 0.5

            final_grade = ( (final_of_kind("hw") * hw_weight_percent)
            + (final_of_kind("lab") * lab_weight_percent)
            + (final_of_kind("exam") * exam_weight_percent))

            print ("Final grade = ", final_grade)


            Note: the alignment in the assignment of final_grade is frowned up on sometimes, because it is not according to PEP8, but I use it for readability.







            share|improve this answer













            share|improve this answer



            share|improve this answer











            answered May 1 at 17:39









            Jan Kuiken

            73338




            73338











            • thanks Jan. I like your solution more it is easier for me to follow. The above solution is beyond my level of experience
              – Erich Purpur
              May 2 at 15:31
















            • thanks Jan. I like your solution more it is easier for me to follow. The above solution is beyond my level of experience
              – Erich Purpur
              May 2 at 15:31















            thanks Jan. I like your solution more it is easier for me to follow. The above solution is beyond my level of experience
            – Erich Purpur
            May 2 at 15:31




            thanks Jan. I like your solution more it is easier for me to follow. The above solution is beyond my level of experience
            – Erich Purpur
            May 2 at 15:31












             

            draft saved


            draft discarded


























             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f193354%2fprogram-to-compute-final-grade-for-weighted-assignments%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            Greedy Best First Search implementation in Rust

            Function to Return a JSON Like Objects Using VBA Collections and Arrays

            C++11 CLH Lock Implementation