Почему при raise MyError получается TypeError
@python_quizРазберем этот квиз
Коротко: в приведённом коде попытка поднять класс исключения без создания его экземпляра приводит к ошибке при инстанцировании — и в итоге в блоке except попадает TypeError.
Исходный код

Что здесь происходит — пошагово
- Определён класс
MyError, унаследованный от Exception. Его__init__требует один аргумент — msg. - В блоке try выполняется
raise MyError. Это неraise MyError()и неraise MyError('...'), а ссылка на сам класс. - Когда вы делаете
raise <класс>, интерпретатор пытается создать экземпляр этого класса, вызвав конструктор без аргументов. - Поскольку
MyError.__init__требует обязательный параметр msg, попытка инстанцировать класс без аргумента вызываетTypeError(недостаточно аргументов для__init__). - Этот
TypeErrorперехватываетсяexcept Exception as e, и затем печатается имя класса исключения — "TypeError".
Если запустить пример, в выводе будет:

Варианты, которые могли бы случиться (и почему они не происходят)
- "Исключение
MyError": это могло быть, если бы класс имел конструктор с подписью, позволяющей вызов без аргументов (например,__init__(self,msg=None)) или если бы вы поднимали уже созданный экземпляр. - "Экземпляр
MyError": это произошло бы, если бы вы явно подняли экземпляр, напримерraise MyError('something'). Тогда except поймает экземплярMyErrorи тип напечатает "MyError". - "Ничего не будет поймано": неверно, потому что при инстанцировании класса действительно возникает
TypeError, а он наследуется от Exception — следовательно, будет пойман.
Демонстрация других вариантов
1) Поднять экземпляр явно:

Вывод:

2) Сделать msg опциональным, тогда raise MyError сработает:

Вывод:

Практические рекомендации
- Обычно лучше делать аргументы
__init__у исключений опциональными (msg=None) или наследовать стандартные Exception, позволяя передавать строку в базовый класс:super().__init__(msg). Так исключение можно безопасно как поднимать классом, так и экземпляром. - Предпочтительнее явно поднимать экземпляр (
raise MyError("desc")) — это явнее и предсказуемее. - Помните: raise <класс> приводит к автоматическому вызову конструктора без аргументов; если конструктор требует аргументы, это приведёт к
TypeErrorво время raise.
Итог
В исходном коде raise MyError приводит к попытке создать экземпляр без аргумента, это вызывает TypeError при вызове __init__, и именно этот TypeError перехватывается и печатается.