Lately, I've been adding asserts
to nearly every single function I make to validate every input as sort of a poor-man's replacement for type checking or to prevent myself from accidentally inputting malformed data while developing. For example,
def register_symbol(self, symbol, func, keypress=None):
assert(isinstance(symbol, basestring))
assert(len(symbol) == 1)
assert(callable(func))
assert(keypress is None or type(keypress) is int)
self.symbols_map[symbol] = (func, keypress)
return
However, I'm worried that this goes against the idea of duck typing, and that I might be going too overboard or constricting myself unnecessarily. Can you ever have too many assert statements? When's a good time to stop?
Python's assert statement is a debugging aid, not a mechanism for handling run-time errors. The goal of using assertions is to let developers find the likely root cause of a bug more quickly. An assertion error should never be raised unless there's a bug in your program.
If an assertion fails, then your program should crash because a condition that was supposed to be true became false. You shouldn't change this intended behavior by catching the exception with a try … except block. A proper use of assertions is to inform developers about unrecoverable errors in a program.
Python Assert Multiple Lines. If you want your assertion message to expand to multiple lines: Wrap the message around a set of parentheses. Break the lines as desired.
Syntax for using Assert in Pyhton: In Python we can use assert statement in two ways as mentioned above. assert statement has a condition and if the condition is not satisfied the program will stop and give AssertionError . assert statement can also have a condition and a optional error message.
I only use assert
s if they provide far better diagnostics than the error messages that I would get otherwise. Your third assert
assert(callable(func))
might be an example for such an assert -- if func
is not callable, you will get an error message at a completely different line of code than where the actual error is, and it might not be obvious how the non-callable object ended up in self.symbols_map
. I write "might" because this depends on the rest of your code -- if this is the only place where self.symbols_map
gets updated, the assert might also be unnecessary.
The first and last assert definitely are against the idea of duck-typing, and the second one is redundant. If symbol
isn't a string of length 1, chances are that self.symbols_map[symbol]
will raise a KeyError
anyway, so no need for the asserts.
The last assert is also wrong -- type(keypress)
cannot be None
, and type checks should be done with isinstance()
. There might be very specialised applications where you cannot allow subtypes, but than the check should be performed with type(x) is int
instead of type(x) == int
. Checking for None
should be done by x is None
, not by type(x) is NoneType
.
You should probably write a good set of unit tests -- they will be far more useful than the asserts, and might make almost all of your asserts redundant.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With