Лутц М. - Изучаем Python (1077325), страница 159
Текст из файла (страница 159)
Но какое сообщение будет выводиться в случае исключений-классову По умолчанию выводится имя класса и не очень удобочитаемая информация об объекте экземпляра: »> с1авз ИуВабн рава »> га1ва Мував() тгасзьаск (всв( гвсзпс са!1 1аз(): Е11е "<рузьз11звб>", 11пе 1, ш <вспс1з> га1за МуВап() МуВав: < аа>п .МуВас !пзсапсз а( Ох00885488> Чтобы улучшить сообщение, необходимо переопределить в классе исключения метод герг или згг, чтобы возвращалась желаемая строка, которая будет отображаться, когда ваше исключение будет достигать обработчика по умолчанию: »> с1авв ИуВабе Ззу гарг (ва1(): гвзсгп "баггу--ву а1ззаав! »> га1зв Иуваа() Тгасеэасп (всзс гЗСЕПГ са!1 !аз!): Г>!е "<рузье!!З28>", 11пе 1, ш <вспп1в> га1зе МуВас() МуВаа: бсггу--ау в(в(аяе! Как мы уже знаем, метод перегрузки герг, используемый здесь, вызывается при выводе и при преобразовании экземпляра класса в строку; метод вгг реализует дружественное строковое представление, Глава 28.
Объекты исключений 744 которому инструкции рыпт отдают предпочтение. (Подробнее о методах преобразования в строку рассказывается в разделе «Перегрузка операторов«в главе 24.) Обратите внимание, что если наследовать встроенные классы исключений, как рекомендовалось выше, текст сообщения об ошибке немного изменится — аргументы конструктора автоматически сохраняются в экземпляре и отображаются в тексте сообщения: »> с1азв иуВас(ехсерт!Ьп): рава »> га!ве ИуВас() тгасеьаск (аозт гесеш са11 1ав!); ет1е '<рузпе!1а18>", 1!пе 1, тп <аосс1е> гагзе Иуеао() ИуВао »> с1азв Иувае(Ехсерс!оп): раза »> га!ве иузас('сье', 'ьг!дь!', 'з!ее', 'ое', ' 1!Ев') тгасеьаск (аозт гесеш са11 1азт); ЕТ1е "<рувпе1!в22>", 1тпе 1, тп <воос1е> гатве иуВас('тпе', 'ьгтдп!', в!се', 'ог', '1!те') иуВас; ('тпе', 'ьгтдм ', 'втсе', 'ог', '1!те') Если ваши конечные пользователи могут видеть сообщения об ошибках, порождаемые исключениями, у вас наверняка появится желание определить собственные методы форматирования сообщений на основе перегрузки операторов, как показано здесь.
Возможность автоматического присоединения информации о состоянии к экземплярам — очень удобная особенность, о чем подробнее рассказывается в следующем разделе. Передача данных и поведения в экземплярах Помимо поддержки гибких иерархий классы исключений также являются удобным местом для хранения дополнительной информации в виде атрибутов экземпляров. Когда возбуждается исключение на основе класса, вместе с исключением интерпретатор автоматически передает объект экземпляра класса в виде элемента дополнительных данных. Так же, как и в случае строковых исключений, вы можете получить доступ к экземпляру, указав дополнительную переменную в инструкции !гу. Это обеспечивает естественный способ передачи дополнительных данных и функциональных возможностей обработчику исключения. Пример: передача дополнительных данных в исключениях на основе классов и строк Давайте рассмотрим возможность передачи дополнительных данных на примере и попутно сравним подходы, основанные на использовании классов и строк.
Программа, выполняющая анализ файлов, может со- 745 Исключения на основе классов общать об ошибке форматирования, возбуждая экземплнр исключе- ния, который заполняется дополнительной информацией об ошибке: »> о1авв ГогшатЕггог: овг 1п11 (вв1г, 11пв, г11в): вв11.11пв = 11пв вв1Г.Г11в = (11а »> овб рагввг(): р когда обнаруживается ошибка Га1аа ЕОГШа1ЕГГОГ(42, Г11агсараШ.СХС') >» тгу: рагввг() вхсврс рогшатеггог, х: рг1пт 'Еггог ат', Х.Г11в, Х,11пв Еггог ат враз.тхт 42 В этом примере переменной Х в предложении ехсер( присваивается ссылка на экземпляр, который был сгенерирован во время возбуждения исключения.' Однако с практической точки зрения этот способ не имеет заметных преимуществ перед возможностью передачи составных объектов (например, кортежей, списков или словарей) в виде дополнительных данных строковых исключений, и сам по себе не выглядит достаточным побудительным мотивом к использованию исключений на основе классов.
Ниже приводится эквивалентный фрагмент, в котором используются строковые исключения: »> гогшатеггог = 'гогшатеггог' »> Овг рагввг(): р когда обнаруживается ошибка гаьвв ГогшатЕггог, ('11пв':42, 'Г11е':'враз, тхт') »> тгу: рагввг() ... вхсвр1 ГогшаСЕггог, Х: рг1п1 'Еггог ат', Х('(11в'], Х(' 11пв'] еггог ат враш.тхт 42 На этот раз переменной Х в предложении ехсер1 присваивается словарь с дополнительной информацией, который передается инструкции Как будет показано в следующей главе, доступ к объекту экземпляра класса исключения обеспечнваетса также вторым элементом кортежа, возвращаемого функцией вув.
ехс што — инструментом, который возвращает информацию о самом последнем исключении. Если в предложении вхсврт не указано нмя переменной, можно использовать эту функцию, когда возникает необходимость обратиться к исключению за получением присоединенных к нему данных нли Лля вызова его методов. 746 Глава 28. Объекты исключений гасве. Результат получается тот же самый, но при этом нет необходимости писать определение класса.
Однако подход, основанный на использовании классов, может оказаться более удобным, когда исключение должно обладать еще и поведением. Класс исключения определяет еще и методы, которые можно вызывать из обработчика: с1авв ЕогааСЕггог. бес !пст (ве1(, 1спе, (с1е); ве1(.1спе = 1спе ве)т.(с!е = (с1е бе( 1оцеггог(ве1(): 1оц = преп('тогеасеггог.схс', 'а') рыпс » 1оц, 'еггог ас', ве1(.тс1е. ве1(. 1спе бе( рагвег(): гале ЕогеаСЕггог(40, 'прае.Схт') сгу; рагвег() ехсерт ЕогааСЕггог, ехс: ехс.1оцеггог() При использовании классов методы (такие как 1оццего г) могут наследоваться подклассами, а атрибуты экземпляра (такие как 1!пе и (!1е) предоставляют возможность сохранения информации о состоянии, обеспечивая дополнительный контекст для последующих вызовов методов.
Мы могли бы имитировать этот эффект, передавая простые функции вместе со строковыми исключениями, но это приведет к чрезмерному усложнению программного кода: согеасеггог = "гогеасеггог" бес 1оцЕггог( 1спе, Гс1е). 1оц = орел('(огаасеггог.схс', 'а') ргспс » 1оц, 'еггог ас', т!1е, 1спе бе( рагвег(); гаазе тогвасеггог, (41, 'врае,схс', 1оцеггог) сгу. рагвег() ехсерт ГогеаСЕггог, баСа: баса[2](баса[0], баса[1]) 4 )Гли просто 1одеггог() Естественно, такие функции не могут быть унаследованы как методы класса и не способны хранить информацию о состоянии в атрибутах экземпляра класса (1азэба-вьсражения и глобальные переменные — это самое лучшее, что можно использовать с функциями). Конечно, можно было бы передать экземпляр класса в виде дополнительных данных строковых исключений, чтобы добиться того же самого эффекта, но если мы зашли так далеко, чтобы имитировать исключения на основе классов, лучше уж принять их — нам и так пришлось писать определение класса.
Общие формы инструкции гайе 747 Как уже упоминалось ранее, исключения иа основе классов станут единственно возможными в будущей версии РуС)соп. Но даже если бы это было ие так, существуют веские основания использовать их. Вообще говоря, строковые исключения представляют собой простой ииструмеит, предназначенный для решения простых задач.
Исключения иа основе классов полезны для определения категорий, и оии выглядят предпочтительнее в более сложных приложениях, когда можно извлечь выгоду из возможности сохранять информацию о состоянии и иаследовать атрибуты. Не в каждом приложении требуется мощь ООП, ио преимущества исключений иа основе классов становятся более очевидными с ростом и расширением программ. Общие формы инструкции гаЬе С учетом исключений иа основе классов инструкция гасве может принимать следующие пять форм. Первые две возбуждают строковые исключеиия, следующие две — исключения иа основе классов, и последияя повторно возбуждает текущее исключение (что очень удобно, когда необходимо обеспечить дальнейшее распространение произвольиых исключений): гасве всгспд № Соответствует предложению ехоерс с теи же обыектои га1ве всг1пд, баса № передает дополнительные данные (по уиолчвнию = лопе) га1ве 1пыапсе № то же, что и: гвсзе спзсвпое о1азз, спзсвпов га1ве с1авв, 1пвсапое № Соответствует предложению ехоерс с теи же № ииенеи класса или его суперкласса № Повторно возбуждает текупее исключение гасве В наши дии наиболее часто используется третья форма.
В случае исключеиий иа основе классов РуС)соп всегда требует указывать экземпляр класса. Возбуждая экземпляр, интерпретатор в действительности возбуждает исключение, соответствующее классу экземпляра, а экземпляр передается вместе с исключением в виде элемента дополнительных даииых (как мы уже видели, это отличное место для хранения ииформации, которая может использоваться обработчиком). Для обратной совместимости с версиями РуС)соп, в которых исключения реализованы иа основе строк, можно использовать следующие формы инструкции га с ее: гасве с1азв № То же, что и: гв1зе о)взз() гале с1авв, агд № То же, что и: га1зе о1взз(вгд) гале с1авв, (агд, агд, ...) № То же, что и гвсзе о1взз(вгд, вгд, ) Все оии соответствуют форме гасве с1авв(агд, ...