Program to compute final grade for weighted assignments
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

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.
Group the exam types into another class, say StudentScores.
Expand Scores to also take the percentage. And make final return the percentage.
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)))