Python помещает все встроенные типы исключений в модуль builtins
. Таким образом, независимо от того, где вы оцениваете ZeroDivisionError
, его можно найти. 1
Ваши исключения не находятся в builtins
, они находятся в любом модуле, в котором вы их определили. Поэтому к ним нужно обращаться как mymodule.MyError
или импортировать с чем-то вроде from mymodule import MyError
.
Кроме того, как указывает Н. Чаухан в комментарии , вам редко требуется больше, чем горстка открытых типов исключений - часто только один. У вас может быть 30 различных типов ошибок, которые имеют значение внутренне , но ваши пользователи, вероятно, заботятся только об 1 или 2 различных типах ошибок, так что вы можете сделать свои 30 типов всеми подклассами 1 или 2 базовых классов, и ваши пользователи должны только import
те.
Не могли бы вы сделать такой же трюк? Да, и на самом деле это довольно просто 2 - но это почти всегда плохая идея.
Может показаться, что это было бы удобно для интерактивного программирования в REPL, но в этом нет необходимости. Просто добавьте новый материал в текущий (__main__
) модуль, и он так же доступен, как если бы он был в builtins
, верно? И Python предоставляет синтаксический сахар для этого. Фактически, это именно то, что делает from mymodule import MyError
: он добавляет MyError
в глобальные переменные текущего модуля.
А для неинтерактивного программирования, размещение чего-либо во встроенных программах делает ваш код запутанным и трудным для чтения.
Если я вижу MyError
в каком-то коде и from mymodule import MyError
в верхней части, очевидно, откуда оно взято. Если я этого не сделаю, то нет никакого способа выяснить, откуда взялась MyError
, кроме как путем тщательного поиска по всей базе кода и всем модулям пакетов сайта, импортированным в любое место.
И еще сложнее для IDE и других инструментов, которые помогают вам писать и перемещаться по коду. Если я наведу курсор мыши на MyError
в PyCharm и наверху будет from mymodule import MyError
, PyCharm сразу узнает, откуда он появился и может показать хорошую подсказку с любой информацией, которая кажется полезной. Я могу щелкнуть по нему правой кнопкой мыши, и он может перейти к определению MyError
. Если я включаю статическую проверку типов, она знает, что такое MyError
, и может проверить, что это подкласс Exception
. И так далее. Но без этого import
PyCharm не сможет узнать, что означает MyError
.
1. Когда вы оцениваете ZeroDivisionError
, упрощенная версия его работы состоит в том, что, если это не локальная или свободная переменная, Python ищет ее в глобальных, а если нет, во встроенных программах. (Более подробное объяснение см. В документах eval
и exec
, а для получения полной информации см. Разрешение имен .)
2. Как ты делаешь это? Вы можете заменить другой модуль builtins
на глобальные, которые включают в себя ваши дополнительные материалы, но действительно простой способ - просто import builtins
и просто добавить в него новый материал, такой как builtins.MyError = MyError
.