简体   繁体   中英

How to undo “assert” in python?

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)

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM