The 'answer' in the mark scheme is wrong. It is broken. It doesn't work. In other words, your code is correct. You should use your code, not the mark scheme. To me, it looks as if someone without actual Python programming experience wrote that up and didn't verify if it actually would run. I would not expect future exams to make such blatant errors, and if they did you would have plenty of ground to challenge the results.
For functions defined on a class, when you use the function name as an attribute on an instance and call it, Python will pass in the instance as the first positional argument to the function, automatically. We only use the name self
for that argument by convention.
So for the SetFinalMark()
method, for example, what will happen is that Python passes in the instance as the first argument, and so that's assigned to the name Mark
. You can call it as Chomba.SetFinalMark()
, at which point Mark
is set to reference the instance you named Chomba
. The method then will raise a different exception, because the ExamResult()
class doesn't support comparisons so Mark >= 0
will raise a TypeError
exception (TypeError: '>=' not supported between instances of 'ExaminationPaper' and 'int'
).
And that also means that the GetFinalMark()
method will always fail, because it doesn't take any parameters (TypeError: GetFinalMark() takes 0 positional arguments but 1 was given
).
There are other issues with the mark scheme code. Because there is no self
parameter the implementation of SetGrade
and SetFinalMark
and GetFinalMark
are instead treating Grade
and FinalMark
as global variables, and so will raise NameError
exceptions if you didn't first run into all those TypeError
exceptions. And in Python, the return
statement is not a function. While return(<expression)
works, it surely will confuse beginning programmers and not help when making a distinction between expressions and statements. The (..)
parentheses are really part of the expression and would be redundant if there was a space after return
; you should really use return <expression>
without parentheses.
Finally, and this is an issue with the assignment, not just with the mark scheme, the whole example goes against the Python style guide naming conventions, which are there to help make it easy to spot classes versus other names. Ideally, only ExaminationPaper
should use CamelCase naming, everything else should use snake_case (lower-cased words joined by underscores), including all attribute names, parameters, and method names.
I had a look around, and this looks like the UK May/June 2019 A-level Computer Science exam past paper (#4) (available at several sites, this is the mark scheme one one such site, to go with this past paper). If so, then it looks like the authors got their conventions mixed up. The paper allows for the student to choose between Python, Pascal and Visual Basic, and their code looks like the author applied Visual Basic principles to Python code. In Visual Basic, there is no self
parameter. The choice to allow for multiple implementation languages then also limited how much room there is for applying the normal Python naming conventions.
But if Python conventions don't apply, then I also note that they are also using attribute names as __FinalMark
in the marking scheme, showing a lack of understanding of how Python treats encapsulation. I'll not go into detail here, but I've written an answer before that explains why using double-underscore names is wrong here. That they then completely failed to use the correct attribute names makes their version of the 'correct' implementation for the three methods you were asked to write even more wrong.
If you wanted to implement everything 'correctly' according to the normal Python conventions and style guide (including using properties and a better name for how determining the grade based on 3 thresholds is handled), you'd end up with:
class ExaminationPaper:
def __init__(self, centre_number, candidate_number):
self.paper_id = f"{centre_number}{candidate_number}"
self.grade = "Fail"
self._final_mark = 0
def determine_grade(self, dist_mark, merit_mark, pass_mark):
if self._final_mark >= dist_mark:
self.grade = "Distinction"
elif self._final_mark >= merit_mark:
self.grade = "Merit"
elif self._final_mark >= pass_mark:
self.grade = "Pass"
else:
self.grade = "Fail"
@property
def final_mark(self):
return self._final_mark
@final_mark.setter
def final_mark(self, mark):
if not (0 <= mark <= 90):
raise ValueError(f"Final mark {mark} not in range 0-90")
self._final_mark = mark
chomba = ExaminationPaper(559, 9022)
try:
chomba.final_mark = 80
except ValueError as e:
print("Could not set the final mark:", e)
else:
chomba.determine_grade(80, 70, 55)
print(f"For {chomba.paper_id}, the student was given a {chomba.grade}")
I fully admit that that's well out of reach of an A-level paper, however. :-) And given the mark scheme, you wouldn't even get your marks unless the person marking the paper actually knew enough about Python programming to recognize why the above deviates from the scheme.