views:

87

answers:

4

I've read about when to use assert vs. exceptions, but I'm still not "getting it". It seems like whenever I think I'm in a situation where I should use assert, later on in development I find that I'm "looking before I leap" to make sure the assert doesn't fail when I call the function. Since there's another Python idiom about preferring to use try-except, I generally end up ditching the assert and throwing an exception instead. I have yet to find a place where it seems right to use an assert. Can anyone come up with some good examples?

+2  A: 

Generelly, assert is there to verify an assumption you have about your code, i.e. at that point in time, either the assert succeeds, or your implementation is somehow buggy. An exception is acutally expecting an error to happen and "embracing" it, i.e. allowing you to handle it.

Jim Brissom
A: 

A good example is checking the arguments of a function for consistency:

def f(probability_vector, positive_number):
    assert sum(probability_vector) == 1., "probability vectors have to sum to 1"
    assert positive_number >= 0., "positive_number should be positive"
    # body of function goes here
pberkes
Interesting -- I didn't know that `0.` was shorthand for `0.0`. repl says it is though. I might not use it in real code though because it seems overly "clever" and easily missed. Could be understood as a typo, but 0.0 is always understood to mean a float.
Daenyth
This seems similar to a situation where I had a function that was fetching an element from a 2D matrix. It made sense to assert that the row and column inputs were actually in the bounds of the matrix. But then later I was doing something where I took an element and wanted to do something with adjacent elements. Once I started coding this up, I was having to have special cases when the element was on the edge, because adjacent elements were outside the matrix. It seemed better to just use exceptions instead.
Colin
How would exceptions make it easier to modify the code? When you change the behavior of the function, you still have to modify the exception-raising part, don't you?
pberkes
That's *not* how you use assert. Assertions should fail if the code is flawed, not when input is not quite as expected. If I get a `ValueError` (or similar) from a call to someone else's function, I know that I passed something invalid. But when I get an `AssertionError`, I must assume that the function is broken (see other answers: assertions are sanity checkes). -1
delnan
The decision had nothing to with making it easier to modify the code, it had to do with using a try block instead of checking the values before calling the function.
Colin
@delnan: a fair point, I guess it depends what you're trying to accomplish with the `assert` statement. I use something very close to the first assert quite often as defensive code to make sure that accumulating floating point errors do not make a probability vector invalid. I agree that for a public function in a library, the users should be informed of errors in a more informative way.
pberkes
+6  A: 

A good guideline is using assert when its triggering means a bug in your code. When your code assumes something and acts upon the assumption, it's recommended to protect this assumption with an assert. This assert failing means your assumption isn't correct, which means your code isn't correct.

Eli Bendersky
+4  A: 

tend to use assert to check for things that should never happen. sort of like a sanity check.

Another thing to realize is that asserts are removed when optimized:

The current code generator emits no code for an assert statement when optimization is requested at compile time.

fseto
+1 for pointing out that that asserts are removed if you invoke Python with the `-O` flag. The point is that if you *expect* your code to ever behave differently if you take the asserts out then you're misusing them - they're for debugging only.
Scott Griffiths