Raising your own exceptions
When a function cannot do its job, raise an exception rather than returning an odd value that the caller might not check. Pick the built-in type that fits: ValueError for a bad value, TypeError for a wrong type, KeyError for a missing key.
For errors that belong to your program, define your own class. It only needs a name and a parent:
class OutOfStock(Exception):
pass
def take(stock, item):
if stock.get(item, 0) == 0:
raise OutOfStock(f"no {item} left")
stock[item] -= 1
try:
take({"tea": 0}, "tea")
except OutOfStock as error:
print("sorry:", error)except SomeError as errorgives you the exception object, andstr(error)is its message.- Inherit from
ValueErrororLookupErrorwhen your error is a special case of one, so handlers that already catch the parent keep working. - Write messages that say what went wrong and with which values.
Your task
Define InsufficientFunds as a subclass of ValueError. Write withdraw(balance, amount) returning the new balance, raising ValueError if amount is 0 or less, and InsufficientFunds with a message containing both numbers if amount is more than balance.
The explanation opens here once every check passes.