Python - Исключения, определенные пользователем

Привет, будущие маги Python! Сегодня мы отправляемся в захватывающее путешествие в мир пользовательских исключений в Python. Не волнуйтесь, если вы новичок в программировании; я веду вас шаг за шагом, как я делал это для многих студентов на протяжении многих лет своего преподавания. Так что, возьмите ваши виртуальные палочки (клавиатуры), и давайте погружемся!

Python - User-defined Exception

Пользовательские исключения в Python

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

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

Как создать пользовательское исключение

Создание своего исключения — это так же просто, как приготовление пирога (ну, если не считать простой рецепт пирога). Вам нужно всего лишь создать новый класс, который наследуется от встроенного класса Exception или любого из его подклассов. Давайте посмотрим на простой пример:

class MySpecialError(Exception):
pass

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

Но что если мы хотим, чтобы наше исключение было немного информативнее? Давайте создадим еще одно:

class ValueTooLargeError(Exception):
def __init__(self, message, value):
self.message = message
self.value = value

В этом примере мы добавили метод __init__ к нашему классу исключения. Это позволяет нам передавать дополнительную информацию при поднятии исключения.

Поднятие пользовательских исключений

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

def check_value(value):
max_value = 100
if value > max_value:
raise ValueTooLargeError("Значение слишком велико!", value)
print(f"Значение {value} допустимо.")

# Давайте попробуем
try:
check_value(150)
except ValueTooLargeError as error:
print(f"Ой! {error.message} Значение было {error.value}")

В этом примере мы проверяем, больше ли значение, чем допустимое. Если да, мы поднимаем наше ValueTooLargeError с пользовательским сообщением и фактическим значением.

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

Обработка пользовательских исключений аналогична обработке встроенных исключений. Мы используем надежный блок try-except. Расширим наш предыдущий пример:

def process_value(value):
try:
check_value(value)
except ValueTooLargeError as error:
print(f"Ошибка: {error.message} Значение {error.value} не допускается.")
# Здесь вы могли бы добавить код для обработки ошибки, например, запрос нового значения
else:
print("Значение успешно обработано!")
finally:
print("Проверка значения завершена.")

# Давайте попробуем с разными значениями
process_value(50)
process_value(200)

В этом коде мы используем блок try-except для обработки нашего ValueTooLargeError. Также мы добавили предложение else, которое выполняется, если исключения не抛出, и предложение finally, которое всегда выполняется, независимо от того, произошло исключение или нет.

Полный пример

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

class InsufficientFundsError(Exception):
def __init__(self, balance, amount):
self.balance = balance
self.amount = amount
self.message = f"Недостаточно средств. Баланс: ${balance}, Попытка снятия: ${amount}"

class NegativeAmountError(Exception):
def __init__(self, amount):
self.amount = amount
self.message = f"Не может обработать отрицательную сумму: ${amount}"

class BankAccount:
def __init__(self, balance=0):
self.balance = balance

def deposit(self, amount):
if amount < 0:
raise NegativeAmountError(amount)
self.balance += amount
print(f"Внесено ${amount}. Новый баланс: ${self.balance}")

def withdraw(self, amount):
if amount < 0:
raise NegativeAmountError(amount)
if amount > self.balance:
raise InsufficientFundsError(self.balance, amount)
self.balance -= amount
print(f"Снято ${amount}. Новый баланс: ${self.balance}")

# Давайте используем наш класс BankAccount
account = BankAccount(100)

try:
account.deposit(50)
account.withdraw(30)
account.withdraw(200)  # Это должно поднять InsufficientFundsError
except NegativeAmountError as error:
print(f"Ошибка: {error.message}")
except InsufficientFundsError as error:
print(f"Ошибка: {error.message}")
else:
print("Все транзакции успешно выполнены.")
finally:
print(f"Конечный баланс: ${account.balance}")

В этом примере мы создали класс BankAccount с методами deposit и withdraw. Также мы определили два пользовательских исключения: InsufficientFundsError и NegativeAmountError.

Когда мы пытаемся снять больше денег, чем у нас есть на счету, оно поднимает InsufficientFundsError. Если мы пытаемся внести или снять отрицательную сумму, оно поднимает NegativeAmountError.

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

Заключение

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

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

Вот быстрый справочник методов, которые мы охватили:

Метод Описание
class CustomError(Exception): Создает новый класс исключения
raise CustomError() Поднимает пользовательское исключение
try: Начинает блок try
except CustomError as error: Перехватывает конкретное пользовательское исключение
else: Выполняется, если исключения не было
finally: Всегда выполняется, независимо от исключений

Счастливого кодирования, и愿 ваши исключения всегда будут перехвачены!

Credits: Image by storyset