Ошибка типизации может привести к остановке работы программа на python

Время на прочтение

Ошибка типизации может привести к остановке работы программа на python

Думаю, мы все потихоньку уже привыкаем, что у Python есть аннотации типов: их завезли два релиза назад (3.5) в аннотации функций и методов (PEP 484), и в прошлом релизе (3.6) к переменным (PEP 526).

Так как оба этих PEP были вдохновлены MyPy, расскажу, какие житейские радости и когнитивные диссонансы подстерегали меня при использовании этого статического анализатора, равно как и системы типизации в целом.

Disclamer: я не поднимаю вопрос о необходимости или вредности статической типизациии в Python. Просто рассказываю о подводных камнях, на которые натолкнулся в процессе работы в статически-типизированном контексте.

Дженерики (typing. Generic)

Однако, что делать, если мы пишем библиотеку, и программист, использующий ее не будет пользоваться статическим анализатором?
Заставлять пользователя инициализировать класс значением, а потом хранить его тип?

В поисках ответа на этот вопрос я немного пробежался по модулю typing, и погрузился в мир фабрик.

Ошибка типизации может привести к остановке работы программа на python

Дело в том, что после инициализации инстанции Generic-класса, у нее появляется атрибут __origin_class__, у которого есть аттрибут __args__, представляющий собой кортеж типов. Однако, доступа к нему из __init__, равно как и из __new__, нет. Также его нет в __call__ метакласса. А фишка в том, что в момент инициализации сабкласса Generic он оборачивается в еще один метакласс _GenericAlias, который и устанавливает финальный тип, либо после инициализации объекта, включая все методы его метакласса, либо в момент вызова __getithem__ на нем. Таким образом, никакого способа получить типы дженерика при конструкции объекта нет.

Выкидываем этот мусор, обещал же более универсальное решение

Поэтому я написал себе небольшой дескриптор, решающий эту проблему:

Конечно, в последствие, надо будет переписать для более универсального использования, но суть понятна.

Anyway, you can use whatever way. Maybe __class_getitem__ is even slightly better, at least __class_getitem__ is a documented special method (although its behavior for generics is not).

Функции и алиасы

Да, с дженериками вообще не просто:
К примеру, если мы где-то принимаем функцию как аргумент, то ее аннотация автоматически превращается из ковариантной в контрвариантную:

И в принципе, претензий к логике у меня нет, только решать это приходится через дженерик-алиасы:

Вообще раздел про вариантность типов надо прочитать внимательно, и не на раз.

Обратная совместимость

С этим не ахти: с версии 3.7 Generic – сабкласс ABCMeta, что есть очень удобно и хорошо. Плохо, что это ломает код, если он запущен на 3.6.

Cтруктурное наследование (Stuctural Suptyping)

Однако, особой практической пользы в рантайме по сравнению со множественным наследованием я не заметил.
Похоже, что декоратор проверяет только наличие метода с требуемым именем, даже не проверяя кол-во аргументов, не говоря уже о типизации:

C другой стороны, MyPy, в свою очередь, ведет себя более умно, и подсвечивает несовместимость типов:

Перегрузка операторов

Совсем свежая тема, т.к. при перегрузке операторов с полной типобезопасностью пропадает все веселье. Этот вопрос уже не раз всплывал в баг-треккере MyPy, но он до сих пор кое-где ругается, и его можно смело выключать.
Поясняю ситуацию:

Если метод составного присваивания возвращает NotImplemented, Python ищет сначала __radd__, потом использует __add__, и вуаля.

То же касается и перегрузки любых методов сабклассов вида:

Кое-где предупреждения уже переехали в документацию, кое-где пока срабатывают на проде. Но общее заключение контрибьютеров: оставить такие перегрузки допустимыми.

Python — язык с динамической типизацией типов. Что это значит? Это значит, что переменная связывается с соответствующим типом в момент присваивания значения, а не в момент объявления переменной. Таким образом, в различных участках кода, одна и та же переменная может принимать различные типы.

Для решения этого вопроса на помощь разработчикам приходит Type Hinting, описанный в спецификации PEP 484 и впервые представленный в Python 3.5. Type Hinting зачастую называют ещё Type Annotation и для понимания, пожалуй, второе название лучше. Важно понимать, что Type Annotation — это всего лишь аннотация типа. С помощью TH мы не включаем некий волшебный режим в Python, делающий его языком со статической типизацией. Это всего лишь инструмент сделать код более прозрачным и и понятным. К TH можно относиться как неким комментариям, позволяющим сократить возможные ошибки и упростить последующую его поддержку.

Синтаксис

Основной синтаксис TH представлен в следующем примере:

Указывая тип аргумента обычно ставят двоеточие сразу после названия аргумента без пробелов, затем идет пробел и указание типа. Если необходимо присвоить аргументу значение по умолчанию, то ставим пробелы до и после знака равно. Так же необходимо использовать пробелы до и после стрелочки, указывающей на тип возвращаемых данных.

Чтобы указывать типы простых встроенных типов данных не требуется никаких дополнительных импортов. Чтобы указывать типы структур данных, таких как списки, множества, словари, кортежи — необходимо использовать пекедж typing:

from typing import List, Set, Dict, Tuple, Optional, Callable, Iterator, Union

Также интересным является тип Optional. Скажем, если у нас есть аргумент или возвращаемое значение, которое может быть None, то, чтобы указать корректный тип можно написать так:

Очень удобно использовать альясы типов. Вся типизация, используемая в TH, может довольно сильно ухудшить читаемость кода, если типов будет в избытке, причем всяких сложных. Чтобы упростить код хорошо использовать альясы:

MyPy

Как было упомянуто выше, TH — это всего лишь аннотация, которая сама по себе не будет возвращать никаких ошибок.

Запустив данный код мы не получим никаких ошибок, а выведется число 30. Чтобы проверять корректность TH используются специальные так называемые type checker-ы. MyPy — один из них. Для его установки необходимо поставить pip и затем написать pip install mypy. После чего, написанный вами код можно проверять из терминала командой mypy my_script.py.

Плюсы и минусы TH

Для начала, рассмотрим плюсы использования TH:

  • TH — это еще один крутой способ улучшить документацию своего проекта наряду с docstring-ами.
  • TH могут улучшить опыт работы с IDE путем получения более осмысленного фидбека, автокомплитов и пр.
  • Добавление TH в код заставляет разработчика думать о типизации, что должно приводить к принятию более правильных архитектурных решений.

К сожалению, есть некоторые минусы в использовании TH:

  • Становится физически больше кода и его, порой, уже не так быстро и просто прочесть.
  • Написание TH занимает время разработки.
  • Проекты, использующие TH, могут незначительно занимать больше времени для запуска, особенно, если импортируется пекедж typing.

Когда же целесообразно использовать TH?

  • Если ведется разработка библиотеки/пекеджа для использования другими разработчиками в их проектах, использовать TH крайне рекомендуется.
  • Если вы работаете над большим Python проектом (тысячи строк кода), TH так же будет здорово помогать разобраться в коде и пользоваться им.
  • TH так же хорошо помогают, если для кода будут писаться unit test-ы.
Читать также:  Вопросы с государственной программой развития сельского хозяйства и национальным докладом о ходе или результатах реализации в 2018 году государственной программы "Развитие сельских территорий", оба из которых были опубликованы на портале государственной программы

Безусловно, используя TH надо знать меру. Везде указывать типы — нецелесообразно, потому что это будет противоречить принципам языка, ведь Python поддерживает принцип “duck typing-а”, который гласит, что если объект реализует метод, то мы его используем. Или более складно: если нечто выглядит как утка, плавает как утка и крякает как утка, то это, вероятно, и есть утка! Поэтому, никаких типов строгих в Python и не используется. Зачастую в коде можно встретить такую конструкцию:

def get_name(foo): try: return foo.name except AttributeError: return None

Т.е. Функция работает с любым типом объекта foo, который имеет атрибут name. Программе наплевать на его тип, главное, чтобы было нужное свойство.

Но несмотря на все это, TH — очень мощная вещь, которую следует применять. Как уже частично было сказано ранее, использование TH заставляет разработчика думать при реализации той же функции на более высоком уровне, а не просто думать о том как сделать конкретный функционал. А думать о функционале как бы “сверху”, взглядом архитектора, а не просто разработчика — очень полезно для кода.

Кроме того, несмотря на возможное незначительное увеличение физического количества кода, читать его все равно в конечном итоге намного проще. Давайте рассмотрим пример:

Что такое объект program? Это строка? Это пользовательский объект? Совершенно непонятно. А теперь посмотрим на такой код:

Теперь, при первом же прочтении, становится очевидно, что program — это экземпляр класса BeautifulSoup, реализующий метод find. Без этого пустячного type hint-а пришлось бы затратить какое-то количество времени на то, чтобы разобраться в коде, особенно, если проект очень большой, либо человек уже давно над ним не работал.

Учитывая все вышеописанное можно сделать вывод, что использовать TH необходимо, если только вы не пишите небольшой скрипт на 100 строчек кода. Как минимум указывая типы аргументов у функций и типы возвращаемых ими значений, вы значительно улучшите читаемость кода и значительно упростите жизнь и себе в последующей работой над проектом, и коллегам.

Начнём с того, что все данные в Python являются объектами. Они могут создаваться нами вручную, либо быть изначально встроенными на уровне языка. Объект можно охарактеризовать, как особую область памяти, где хранятся некоторые значения и определённые для этих значений операции.

Проиллюстрировать фундаментальность объектов в разрезе Питона можно, приведя пример общего вида программы на этом языке. Итак:

  • Программа состоит из модулей;
  • Модуль, в свою очередь, представляет собой набор инструкций;
  • Инструкции содержат выражения;
  • Выражения служат для создания и обработки объектов;

Ошибка типизации может привести к остановке работы программа на python

Объекты — базовое понятие в Python.

Ну и вполне закономерно, что объекты можно классифицировать по их типам.

Что такое динамическая типизация

Прежде, чем мы приступим к рассмотрению наиболее употребляемых типов данных в Python, проведём небольшую параллель с другими языками программирования. Всё их множество можно разделить на две составляющие:

  • типизированные языки;
  • нетипизированные (бестиповые) языки.

Нетипизированные языки в основной своей массе сосредоточены на низком уровне, где большинство программ напрямую взаимодействует с железом. Так как компьютер «мыслит» нулями и единицами, различия между строкой и, допустим, классом для него будут заключаться лишь в наборах этих самых 0 и 1. В связи с этим, внутри бестиповых языков, близких к машинному коду, возможны любые операции над какими угодно данными. Результат на совести разработчика.

Python же — язык типизированный. А, раз в нём определено понятие «типа», то должен существовать и процесс распознавания и верификации этих самых «типов». В противном случае вероятны ситуации, когда логика кода окажется нарушенной, а программа выполнится некорректно.

Таким процессом и является типизация. В ходе её выполнения происходит подтверждение используемых типов и применение к ним соответствующих ограничений. Типизация может быть статической и динамической. В первом случае, проверка выполняется во время компиляции, во втором — непосредственно во время выполнения программного кода.

Python — язык с динамической типизацией. И здесь, к примеру, одна и та же переменная, при многократной инициализации, может являть собой объекты разных типов:

В языке со статической типизацией такой фокус не пройдёт:

💭 Адепты и приверженцы разных языков часто спорят о том, что лучше: динамическая типизация или статическая, но, само собой, преимущества и недостатки есть и там, и там.

👍 К плюсам динамической типизации можно отнести:

. Создание разнородных коллекций.
Благодаря тому, что в Python типы данных проверяются прямиком во время выполнения программного кода, ничто не мешает создавать коллекции, состоящие их элементов разных типов. Причём делается это легко и просто:

. Абстрагирование в алгоритмах.
Создавая на Питоне, предположим, функцию сортировки, можно не писать отдельную её реализацию для строк и чисел, поскольку она и так корректно отработает на любом компарируемом множестве.

. Простота изучения.
Не секрет, что изучать Питон с нуля гораздо легче, чем, например, Java. И такая ситуация будет наблюдаться не только для этой пары. Языки с динамической типизацией в большинстве своём лучше подходят в качестве учебного инструмента для новичков в программировании.

🙁 К минусам же динамической проверки типов можно отнести такие моменты, как:

Статически типизированные языки обычно работают быстрее своих динамических братьев, поскольку являются более «тонким» инструментом, оптимизация которого, в каждом конкретном случае, может быть настроена более тщательно и рационально.

Так или иначе, сказать, что «одно лучше другого» нельзя. Иначе «другого» бы не было. Динамически типизированные языки экономят уйму времени при кодинге, но могут обернуться неожиданными проблемами на этапе тестирования или, куда хуже, продакшена. Однако вряд ли кто-то будет спорить с тем, что динамический Python куда более дружелюбный для новичков, нежели статический C++.

Разница между атомарными и структурными типами данных

По одной из классификаций все типы данных в Python делятся на атомарные и ссылочные.

  • числа;
  • строки;
  • списки;
  • кортежи;
  • словари;
  • функции;
  • классы;

Разница между этими двумя группами уходит глубоко в корни языка. Вкратце:

Атомарные объекты, при их присваивании, передаются по значению, а ссылочные — по ссылке

Из результатов видно, что переменной было присвоено именно значение, содержащееся в atom, а не ссылка, указывающая на область памяти.

Посмотрим, как это работает для структурных типов:

Поскольку списки — это ссылочные объекты, то вполне закономерно, что после присваивания переменной передалась именно ссылка на объект list-а и, при печати, на экран были выведены две одинаковые надписи.

Читать также:  Программа которая проверяет жесткий диск на ошибки и битые сектора

Собственно, в этом и вся разница.

Числовые типы

«Все сущее есть Число» — сказал однажды мудрый грек по имени Пифагор. Числа — важнейший и фундаментальнейший из всех типов данных для всех языков программирования. В Python для их представления служит числовой тип данных.

Int (целое число)

Концепция целых чисел проста и естественна. Это числа без дробной части, которые, говоря математическим языком, являются расширением натурального ряда, дополненного нулём и отрицательными числами.

# примеры целых чисел
a = -3000
b = 0
c = 9000

Там, где есть числа, есть и математика. Поэтому резонно, что целые числа используются для исчисления всевозможных математических выражений. Также применяется в качестве описаний количественных свойств какого-либо объекта.

Float (число с плавающей точкой)

Действительные или вещественные числа придуманы для измерения непрерывных величин. В отличие от математического контекста, ни один из языков программирования не способен реализовать бесконечные или иррациональные числа, поэтому всегда есть место приближению с определенной точностью, из-за чего возможны такие ситуации:

В плане записи, ничем не отличаются от

# примеры вещественных чисел
zero = 0.0
pi = 3.14
e = 2.71

В плане использования — тоже, разве что в любых мало-мальски серьёзных вычислениях без

Complex (комплексное число)

Привет высшей математике! Как вещественный ряд расширяет множество рациональных чисел, так и ряд комплексных чисел расширяет множество вещественных. Показательной особенностью комплексного ряда является возможность извлечения корня из отрицательных чисел.

В Python комплексные числа задаются с помощью функции

Помните, что операция сравнения для комплексных чисел не определена:

Комплексные числа широко применяются, например, для решения дифференциальных уравнений.

Подробнее про числа в Python:

Bool (логический тип данных)

В каком-то смысле наиболее простой и самый понятный из всех типов данных. У bool есть всего два значения:

  • Истина (True);
  • Ложь (False).

Однако за этой простотой кроется колоссальный пласт теории в виде булевой алгебры.

# пример bool
pravda = True
lozh = False

Переменные логического типа нужны для реализации ветвлений, они применяются для установки флажков, фиксирующих состояния программы, а также используются в качестве возвращаемых значений для функций, названия которых, зачастую, начинаются на «is» (isPrime, isEqual, isDigit). То есть тех, которые, на человеческом языке, отвечали бы на вопрос одним словом «Да» или «Нет».

Подробнее про логический тип данных в Python:

Последовательности

Ещё одно понятие из математики. Там, последовательность — есть нумерованный набор элементов, в котором возможны их повторения, а порядок имеет значение. Определение Питона схоже с математическим: здесь последовательностью зовётся упорядоченная коллекция объектов.

Str (строка)

Строки, пожалуй, единственный объект, который может сравниться по степени своей используемости с числовым типом данных. Тавтологическое, но полное определение, справедливое для Python звучит так:

строка — это последовательность односимвольных строк.

Важность строк велика в первую очередь для людей, ведь понятно, что вся письменная речь может рассматриваться, как множество строк. А так как человеку свойственно обмениваться информацией именно в виде набора слов, то можно говорить о практически неограниченном количестве областей применения строкового типа данных. Строки, строки everywhere!

Больше информации по строкам в Python тут:

List (список)

Само название списков говорит об их предназначении быть объектами для хранения наборов данных. Список покупок, подарков, результатов матчей, ip клиентов или объектов типа Student. Списки в Python — это эдакие массивы из прочих языков «на максималках».

Подробнее про работу со списками читайте тут:

Tuple (кортеж)

Кортежи в языке Python можно рассматривать, как неизменяемые списки со всеми вытекающими:

Использование кортежей оправдано, когда разработчику важна скорость работы или неизменяемость элементов последовательности.

Подробнее о кортежах в Python:

Dict (словарь)

Словари хоть и являются набором данных, однако не считаются последовательностью, потому как представляют собой неупорядоченный набор пар ключ:значение.

Применяются они, когда для работы требуется тип данных концептуально схожий с обычным телефонным справочником, где каждая запись — есть пара сопоставленных друг с другом значений, по одному из которых (уникальному ключу) можно получить второе (собственно, значение).

Про словари в Python читайте тут:

Set (множество)

Ещё один «набор, но не последовательность».

Мы хотим видеть множество, если нам не существенен порядок элементов, но важна их уникальность.

Работа с множествами описана в этой статье:

Файл

Работа с файлами, хранящимися где-то на внешнем носителе, в Python реализована в виде объектов-файлов. Они относятся к объектам базового типа, но обладают весьма характерной чертой: нельзя создать экземпляр объекта-файла при помощи литералов.

Чтобы начать работу с файлами, нужно вызвать функцию и передать ей в качестве аргументов имя файла из внешнего источника и строку, описывающую режим работы функции:

f = open(‘filename.txt’, ‘w’)

Операции с файлами могут быть разными, а, следовательно, разными могут быть и режимы работы с ними:

  • — выбирается по умолчанию, означает открытие файла для чтения;
  • — файл открывается для записи (если не существует, то создаётся новый);
  • — файл открывается для записи (если не существует, то генерируется исключение);
  • — режим записи, при котором информация добавляется в конец файла, а не затирает уже имеющуюся;
  • — открытие файла в двоичном режиме;
  • — ещё одно значение по умолчанию, означающее открытие файла в текстовом режиме;
  • — читаем и записываем.

Range object (a type of iterable)

Крутая особенность языка Python состоит в наличии в нём встроенной функции , которая способна генерировать непрерывную последовательность целых чисел:

Она крайне удобна для создания циклов

None

— специальный объект внутри Питона. Он означает пустоту, всегда считается «Ложью» и может рассматриваться в качестве аналога для языка C/С++. Помимо этого, возвращается функциями, как объект по умолчанию.

На практике этот тип данных может быть полезен, когда вы, к примеру, захотите заполнить список отсутствующими значениями, чтобы он разросся, и можно было обращаться к старшим элементам по индексу.

Работа с типами в Python

Нет ничего проще, чем узнать тип данных объекта в Python:

Как поменять тип данных

В богатом арсенале Питона есть встроенные функции для приведения типов —

: встроенная функция для приведения типа не модифицирует переданное значение, а возвращает новое значение другого типа.

Отличие type() от isinstance()

В отличие от возвращает не тип данных аргумента, а булево значение, говорящее о том, принадлежит объект к определенному классу или нет:

умеет проверять принадлежность объекта хотя к одному типу из кортежа, переданного в качестве второго аргумента:

Важным отличием также является то, что «знает» о наследовании. Функция воспринимает объект производного класса, как объект базового.

А вот вывод результата работы функции

Здесь видно, что для производный класс есть производный.

Читать также:  В Школе осознанного родительства есть занятия как для родителей, так и для детей

Данный урок посвящен исключениям и работе с ними. Основное внимание уделено понятию исключения в языках программирования, обработке исключений в Python, их генерации и созданию пользовательских исключений.

Исключения в языках программирования

Исключениями (exceptions) в языках программирования называют проблемы, возникающие в ходе выполнения программы, которые допускают возможность дальнейшей ее работы в рамках основного алгоритма. Типичным примером исключения является деление на ноль, невозможность считать данные из файла (устройства), отсутствие доступной памяти, доступ к закрытой области памяти и т.п. Для обработки таких ситуаций в языках программирования, как правило, предусматривается специальный механизм, который называется обработка исключений (exception handling).

Исключения разделяют на синхронные и асинхронные. Синхронные исключения могут возникнуть только в определенных местах программы. Например, если у вас есть код, который открывает файл и считывает из него данные, то исключение типа “ошибка чтения данных” может произойти только в указанном куске кода. Асинхронные исключения могут возникнуть в любой момент работы программы, они, как правило, связаны с какими-либо аппаратными проблемами, либо приходом данных. В качестве примера можно привести сигнал отключения питания.

В языках программирования чаще всего предусматривается специальный механизм обработки исключений. Обработка может быть с возвратом, когда после обработки исключения выполнение программы продолжается с того места, где оно возникло. И обработка без возврата, в этом случае, при возникновении исключения, осуществляется переход в специальный, заранее подготовленный, блок кода.

Различают структурную и неструктурную обработку исключений. Неструктурная обработка предполагает регистрацию функции обработчика для каждого исключения, соответственно данная функция будет вызвана при возникновении конкретного исключения. Для структурной обработки язык программирования должен поддерживать специальные синтаксические конструкции, которые позволяют выделить код, который необходимо контролировать и код, который нужно выполнить при возникновении исключительной ситуации.

В Python выделяют два различных вида ошибок: синтаксические ошибки и исключения.

Синтаксические ошибки в Python

Синтаксические ошибки возникают в случае если программа написана с нарушениями требований Python к синтаксису. Определяются они в процессе парсинга программы. Ниже представлен пример с ошибочным написанием функции print.

i ():
prin()

Traceback (most recent call last):
File , line , module
prin()
: name defined

Исключения в Python

Второй вид ошибок – это исключения. Они возникают в случае если синтаксически программа корректна, но в процессе выполнения возникает ошибка (деление на ноль и т.п.). Более подробно про понятие исключения написано выше, в разделе “исключения в языках программирования”.

a
b
c a b
Traceback (most recent call last):
File , line , module
c a b
: division by zero

В Python исключения являются определенным типом данных, через который пользователь (программист) получает информацию об ошибке. Если в коде программы исключение не обрабатывается, то приложение останавливается и в консоли печатается подробное описание произошедшей ошибки с указанием места в программе, где она произошла и тип этой ошибки.

Иерархия исключений в Python

Существует довольно большое количество встроенных типов исключений в языке Python, все они составляют определенную иерархию, которая выглядит так, как показано ниже.

Как видно из приведенной выше схемы, все исключения являются подклассом исключения BaseException. Более подробно об иерархии исключений и их описании можете прочитать здесь.

Обработка исключений в Python

()
:
val ((«input number: «))
tmp val
(tmp)
e:
( (e))
()

Вывод программы при вводе нулевого числа будет таким.

start input number: 0 Error! stop

()
val ((“ number: “))
tmp val
(tmp)
()

Если ввести 0 на запрос приведенной выше программы, произойдет ее остановка с распечаткой сообщения об исключении.

tmp = 10 / val

ZeroDivisionError: division by zero

Обратите внимание, надпись stop уже не печатается в конце вывода программы.

Согласно документу по языку Python, описывающему ошибки и исключения, оператор try работает следующим образом:

  • Вначале выполняется код, находящийся между операторами try и except.
  • Если в ходе его выполнения исключения не произошло, то код в блоке except пропускается, а код в блоке try выполняется весь до конца.
  • Если исключение происходит, то выполнение в рамках блока try прерывается и выполняется код в блоке except. При этом для оператора except можно указать, какие исключения можно обрабатывать в нем. При возникновении исключения, ищется именно тот блок except, который может обработать данное исключение.
  • Если среди except блоков нет подходящего для обработки исключения, то оно передается наружу из блока try. В случае, если обработчик исключения так и не будет найден, то исключение будет необработанным (unhandled exception) и программа аварийно остановится.

Для указания набора исключений, который должен обрабатывать данный блок except их необходимо перечислить в скобках (круглых) через запятую после оператора except.

Если бы мы в нашей программе хотели обрабатывать только ValueError и ZeroDivisionError, то программа выглядела бы так.

()
:
val ((«input number: «))
tmp val
(tmp)
(, ):
()
()

Или так, если хотим обрабатывать ValueError, ZeroDivisionError по отдельность, и, при этом, сохранить работоспособность при возникновении исключений отличных от вышеперечисленных.

()
:
val ((«input number: «))
tmp val
(tmp)
:
()
:
()
:
()
()

Существует возможность передать подробную информацию о произошедшем исключении в код внутри блока except.

rint()
:
val ((«input number: «))
tmp val
(tmp)
ve:
(.format(ve))
zde:
(.format(zde))
ex:
(.format(ex))
()

Использование finally в обработке исключений

Для выполнения определенного программного кода при выходе из блока try/except, используйте оператор finally.

:
val ((«input number: «))
tmp val
(tmp)
:
()
:
()

Не зависимо от того, возникнет или нет во время выполнения кода в блоке try исключение, код в блоке finally все равно будет выполнен.

Если необходимо выполнить какой-то программный код, в случае если в процессе выполнения блока try не возникло исключений, то можно использовать оператор else.

:
f (, )
line f:
(line)
f.close()
e:
(e)
:
(«File was readed»)

Генерация исключений в Python

Для принудительной генерации исключения используется инструкция raise.

Самый простой пример работы с raise может выглядеть так.

:
()
e:
(«Exception exception » (e))

Таким образом, можно “вручную” вызывать исключения при необходимости.

Пользовательские исключения (User-defined Exceptions) в Python

В Python можно создавать собственные исключения. Такая практика позволяет увеличить гибкость процесса обработки ошибок в рамках той предметной области, для которой написана ваша программа.

Для реализации собственного типа исключения необходимо создать класс, являющийся наследником от одного из классов исключений.

():

:
val ((«input positive number: «))
val :
NegValException(«Neg val: » (val))
(val )
NegValException e:
(e)

Если вам интересна тема анализа данных, то мы рекомендуем ознакомиться с библиотекой Pandas. На нашем сайте вы можете найти вводные уроки по этой теме. Все уроки по библиотеке Pandas собраны в книге “Pandas. Работа с данными”.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *