Как создать собственное исключение
Иерархия исключений не является ни закрытой, ни законченной, и Вы всегда можете расширить ее, если хотите или если Вам нужно создать свой собственный мир, заполненный Вашими собственными исключениями.
Это может быть полезно, когда Вы создаете сложный модуль, который обнаруживает ошибки и вызывает исключения, и Вы хотите, чтобы исключения легко отличались от любых других, представленных Python.
Это достигается путем определения собственных, новых исключений как подклассов, производных от предопределенных.
Примечание: если Вы хотите создать исключение, которое будет использоваться как специализированный случай любого встроенного исключения, извлеките его только из этого. Если Вы хотите создать свою собственную иерархию и не хотите, чтобы она была тесно связана с деревом исключений Python, выведите его из любого из верхних классов исключений, например Exception. р>
Представьте, что Вы создали совершенно новую арифметику, управляемую Вашими собственными законами и теоремами. Понятно, что деление тоже было переопределено и должно вести себя не так, как обычное деление. Также ясно, что это новое деление должно вызывать свое собственное исключение, отличное от встроенного ZeroDivisionError, но разумно предположить, что в некоторых обстоятельствах Вам (или пользователям Вашей арифметики) может потребоваться одинаковое отношение ко всем делениям на ноль.
Подобные требования могут быть выполнены способом, представленным в редакторе. Посмотрите на код, и давайте проанализируем его:
- Мы определили наше собственное исключение с именем
MyZeroDivisionError
, полученное из встроенногоZeroDivisionError
. Как видите, мы решили не добавлять новые компоненты в класс;
В сущности, исключение этого класса можно, в зависимости от желаемой точки зрения, рассматривать его как обычный ZeroDivisionError или рассматривать отдельно; - Функция
doTheDivision()
вызывает исключениеMyZeroDivisionError
илиZeroDivisionError
, в зависимости от значения аргумента;
Функция вызывается в общей сложности четыре раза, в то время как первые два вызова обрабатываются с использованием только одной ветвиexept
(более общей) и двух последних с двумя разными ветвями, с возможностью различать исключения (не забывайте: порядок ветвей имеет принципиальное значение!).
Code
class MyZeroDivisionError(ZeroDivisionError):pass
def do_the_division(mine):
if mine:
raise MyZeroDivisionError("some worse news")
else:
raise ZeroDivisionError("some bad news")
for mode in [False, True]:
try:
do_the_division(mode)
except ZeroDivisionError:
print('Division by zero')
for mode in [False, True]:
try:
do_the_division(mode)
except MyZeroDivisionError:
print('My division by zero')
except ZeroDivisionError:
print('Original division by zero')