Reputation: 301
In an early function, let's call it a
, i have to make sure that the a
function doesn't produce an answer that is too small (let's say, answer must be bigger than 10).
But later on, in a second function b
(which uses function a
as one of its inputs), it is okay if the same answer that is being modified is smaller than the earlier assert
statement.
Is there a way to do this?
When function b
produced an answer that was too small, I tried to save how small the answer was in variable, but I'm still getting assert errors when I run doctest.
def grade_on_project(student_project_score, max_score, overall_score):
project_grade = student_project_score / max_project_score
assert project_grade > 0.6 # (student fails the class if any of their scores on a project are too low)
overall_score +=student_project_score
return overall_score
def who_fails_first(operation, person1, person2)
if (operation(person1, max_score, person1) <= 150 and (operation(person2, max_score, overall_score) > 150:
print(student 1 failed)
if (operation(person2, max_score, overall_score) <= 150 and (operation(person1, max_score, overall_score) > 150:
print(student 2 failed)
who_fails_first(grade_on_project, 5, 9)
Upvotes: 0
Views: 149
Reputation: 101909
Assertions should not be used to implement logic of some piece of code. Why? Because you have no guarantee that they are actually raised!
$python -c 'assert False'
Traceback (most recent call last):
File "<string>", line 1, in <module>
AssertionError
$python -O -c 'assert False' # doesn't raise an error!
$
-O
option is for "optimizations". But it also remove all assertions
assert
s should be used to debug, checking for conditions that should never happen in a well written program.
If you want to handle special inputs in some way you should use exceptions:
def grade_on_project(student_project_score, max_score, overall_score):
project_grade = student_project_score / max_project_score
if project_grade > 0.6:
raise ValueError('Student fails if at least one project grade is too low.')
overall_score +=student_project_score
return overall_score
Or you might write a custom exception like:
class StudentFailed(ValueError):
def __init__(self, message, grade):
super(StudentFailed, self).__init__(message)
self.grade = grade
And change the if
to:
if project_grade > 0.6:
raise StudentFailed('One project has grade too low.', project_grade)
Then when you catch the exception you can still access the grade that made it fail via the grade
attribute of the exception.
If you don't want to raise the exception in a particular situation you could add a parameter, such as low_grade_is_ok
and modify the function as:
def grade_on_project(student_project_score, max_score,
overall_score, low_grade_is_ok=False):
project_grade = student_project_score / max_project_score
if not low_grade_is_ok and project_grade > 0.6:
raise ValueError('Student fails if at least one project grade is too low.')
overall_score +=student_project_score
return overall_score
Then in the function where you don't want to raise an exception you can call it with low_grade_is_ok=True
and no exception will be raised in that case.
Upvotes: 2