Info
Content

08.07.2024

Input

Когда в коде вызывается функция input(), программа останавливается и ждет пользовательского ввода. Это встроенная функция
Функция input() конвертирует ввод в строку по умолчанию (python2 задает тип данных автоматически и не требует явно задавать тип (если в ответ на input() введешь число, то получится int, а если строку, то str))

Еще в Python2 была функция raw_input(), она как раз работает как input() в Python3

Эта функция возвращает строку

>>> input("-> ")
-> test
'test'

Как видно единственно возможный опциональный параметр (prompt) выводится перед приглашением к вводу без переноса строки

>>> input("multiline\nprompt: ")
multiline
prompt: string
'string'

Чтобы твоя программа с использованием функции input() была эффективной:

  • Используй понятный prompt, например вместо 'введите значение' напиши 'укажите свой возраст'. Это позволит избежать конфузов при использовании твоей программы
  • Проверяй пользовательский ввод. Лучше сразу убедиться что пользовательский ввод не проходит по требованиям чем вывалиться в ошибку в конце работы программы из-за некорректного ввода пользователя. Проверь что числовое значение входит в допустимые рамки (наверное если на запрос возраста пользователь ввел 220, то что-то не так), убедись что текстовый ввод по размеру не превышает лимит, убедись что ввод не пустой (ну и вдовесок что на запрос числа мы не получили строку)
  • Используй блоки try-except для обработки некорректного пользовательского ввода и предоставь пользователю информативный текст ошибки чтобы он исправил свой ввод

Exceptions

В Python все исключения это экземпляры класса который отнаследован от класса BaseException
Классы могут наследоваться друг от друга. Так ZeroDivisionError происходит от ArithmeticError, который происходит от Exception, который происходит от BaseException

Два не связанных общим родителем класса не являются эквивалентными, даже если у них одинаковое имя
То есть если мы укажем в except имя родительского класса, например LookupError, то нам не важно произошел у нас IndexError или KeyError

Ниже код демонстрирующий, что под except B подпадает и сам B, и его сын, и его внук

>>> class B(Exception):
...     pass
...
>>> class C(B):
...     pass
...
>>> class D(C):
...     pass
...
>>> for cls in [B, C, D]:
...     try:
...         raise cls()
...     except B:
...         print("B: " + str(cls))
...
B: <class '__main__.B'>
B: <class '__main__.C'>
B: <class '__main__.D'>

Встроенные классы исключений могут быть родительскими для классов определенных программистом. Для описания своих классов исключений рекомендуется наследоваться от класса Exception, а не от BaseException

BaseException - это базовый класс для всех встроенных исключений
Exception - это базовый класс для всех нефатальных исключений и он наследуется от BaseException (именно от Exception нужно наследовать свои кастомные исключения)

Пример: исключение KeyboardInterrupt вызывается когда пользователь завершает нашу программу с помощью Control-C, так как это фатальное исключение, то оно наследуется от BaseException, а не от Exception

Могут быть обработаны все перечисленные исключения (а не только нефатальные)
Пример подтверждающий это:

>>> import time
>>> try:
...   time.sleep(60)
... except KeyboardInterrupt:
...   time.ctime()
...   time.sleep(5)
...   time.ctime()
...   print("KeyboardInterrupt: CTRL-C was pressed")
...
^C'Tue Jul  9 02:13:25 2024'
'Tue Jul  9 02:13:30 2024'
KeyboardInterrupt: CTRL-C was pressed

Иерархия наследования классов исключений:

BaseException
 ├── BaseExceptionGroup
 ├── GeneratorExit
 ├── KeyboardInterrupt
 ├── SystemExit
 └── Exception
      ├── ArithmeticError
      │    ├── FloatingPointError
      │    ├── OverflowError
      │    └── ZeroDivisionError
      ├── AssertionError
      ├── AttributeError
      ├── BufferError
      ├── EOFError
      ├── ExceptionGroup [BaseExceptionGroup]
      ├── ImportError
      │    └── ModuleNotFoundError
      ├── LookupError
      │    ├── IndexError
      │    └── KeyError
      ├── MemoryError
      ├── NameError
      │    └── UnboundLocalError
      ├── OSError
      │    ├── BlockingIOError
      │    ├── ChildProcessError
      │    ├── ConnectionError
      │    │    ├── BrokenPipeError
      │    │    ├── ConnectionAbortedError
      │    │    ├── ConnectionRefusedError
      │    │    └── ConnectionResetError
      │    ├── FileExistsError
      │    ├── FileNotFoundError
      │    ├── InterruptedError
      │    ├── IsADirectoryError
      │    ├── NotADirectoryError
      │    ├── PermissionError
      │    ├── ProcessLookupError
      │    └── TimeoutError
      ├── ReferenceError
      ├── RuntimeError
      │    ├── NotImplementedError
      │    └── RecursionError
      ├── StopAsyncIteration
      ├── StopIteration
      ├── SyntaxError
      │    └── IndentationError
      │         └── TabError
      ├── SystemError
      ├── TypeError
      ├── ValueError
      │    └── UnicodeError
      │         ├── UnicodeDecodeError
      │         ├── UnicodeEncodeError
      │         └── UnicodeTranslateError
      └── Warning
           ├── BytesWarning
           ├── DeprecationWarning
           ├── EncodingWarning
           ├── FutureWarning
           ├── ImportWarning
           ├── PendingDeprecationWarning
           ├── ResourceWarning
           ├── RuntimeWarning
           ├── SyntaxWarning
           ├── UnicodeWarning
           └── UserWarning

Try Except

В Python есть два вида ошибок:

  • синтаксические - возникает на этапе парсинга кода
  • логические - исключения возникающие во время работы кода (и они не фатальны)

Имена встроенных исключений это встроенные идентификаторы, а не зарезервированные ключевые слова (значит можно и переопределить)

Конструкция try-except:

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

Внутри except задается имя класса исключения, будут обработаны также все производные от указанного класса (но не наоборот). То есть когда мы указываем BaseException, то под это условие подпадают вообще все исключения, а если указываем ArithmeticError, то будут обработаны только FloatingPointError, OverflowError и ZeroDivisionError

Будут обработаны не только исключения произошедшие непосредственно внутри блока try, но и исключения произошедшие внутри функций, вызванных внутри try


Если произойдет исключение внутри секции except, то будет получена цепочка исключений

>>> try:
...   1 / 0
... except ZeroDivisionError() as err: # из-за скобок около имени класса произойдет исключение
                                       # потому что скобками мы вызываем конструктор и получаем экземпляр класса
                                       # а без скобок передаем идентификатор класса
...   print("Handling run-time error:", err)
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
TypeError: catching classes that do not inherit from BaseException is not allowed

Raise

Ключевое слово raise позволяет искуственно стриггерить указанное исключение

>>> raise KeyboardInterrupt
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyboardInterrupt

>>> raise BrokenPipeError
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
BrokenPipeError

>>> raise BaseException
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
BaseException

Будет вызван конструктор указанного класса (туда можно передать аргументы)

Форма raise ValueError это сахар для полной записи raise ValueError()

No Comments
Back to top