- ВКонтакте
- РћРТвЂВВВВВВВВнокласснРСвЂВВВВВВВВРєРСвЂВВВВВВВВ
- РњРѕР№ Р В Р’В Р РЋРЎв„ўР В Р’В Р РЋРІР‚ВВВВВВВВРЎР‚
- Viber
- Skype
- Telegram
Можно ли так использовать try except "вместо if" для управления логикой программы?
Если я в каждой функции при несоблюдении каких-то условий буду выбрасывать исключение это норм? Или так не делается? Можно ли в целом использовать try except для управления логикой приложения и если да то как это правильно и лучше делать?
Просто если в функции не срабатывает исключение, но что-то идет не так как нужно мне. То как это потом отловить. Мне нужно будет каждый раз например проверять что возвращает эта функция, но это вроде уже не так удобно)
Заранее извиняюсь если вопрос глупый, прошу не минусовать) Правда не могу понять. Код ниже для примера.
# Обработка ошибок в логике
class CustomError(Exception):
def __init__(self, message):
super().__init__(message)
def __str__(self):
return f"{super().__str__()}"
# Любая функция
def get_yandex(self):
url = f"https://ya.ru"
response = requests.get(url)
if response.status_code == 200:
return response.json()
else:
raise CustomError(f"Ошибка при получении токена: {response.text}")
Ответы (4 шт):
Исключения - это предмет постоянных споров. Если они делают вашу программу более читаемой, вы можете их использовать.
Например в питоне, встроенная исключение StopIteration
используется для контроля потока итератора. Т.е. в питоне это считается норм.
Вещи которые необходимо держать в уме:
Исключения могут негативно повлиять на производительность. (Особенно в C++).
Если расстояние между где исключение кидается и ловится большое, это может быть неожиданным и ухудшит читаемость вашей программы.
Если вы кидаете ислючения слишком часто, это может затруднить отлаживание вашей программы.
Если для программы нормально происходящее, то так лучше не делать, а если ненормально, то делать.
Ну вот смотрите, если у вас будет, например, такой пример. Вы хотите последовательно сделать несколько действий, объединённых некоей логикой. И при этом не хотите делать лишних действий. То как это будет выглядеть при двух разных подходах. Код довольно условный:
# вариант с if
def aggregate_data(params):
result1 = get_data1(params)
if not result1.ok:
return state.error
result2 = get_data2(params)
if not result2.ok:
return state.error
result3 = get_aggregate(result1.data, result2.data)
if not result3.ok:
return state.error
return result3
result = aggregate_data(params)
if result != state.error:
print_aggregate(result)
else:
print('ошибка!')
# вариант с exception в нижележащих функциях
def aggregate_data(params):
result1 = get_data1(params)
result2 = get_data2(params)
result3 = get_aggregate(result1.data, result2.data)
return result3
try:
result = aggregate_data(params)
print_aggregate(result)
except:
print('ошибка!')
На мой взгляд использование исключений позволяет избежать лишних проверок. Функция не смогла нормально выполниться - она выбросила ошибку - эта ошибка поймалась там, где вам её удобнее всего обработать. Те блоки кода, которые были зависимы от правильного выполнения предыдущего кода, автоматически не стали выполняться, без дополнительных проверок.
По моему субъективному опыту использования исключений в Python
улучшает написание кода, его чтение и обработку возможных случаев.
Попробуйте написать чистую программу которая будет что-то принимать и что-то отдавать, в самом начале перечислите исключения которые могут возникнуть, опишите их названия понятными словами или добавьте комментарий.
class FirstScopedException(Exception):
pass
class SecondScopedException(Exception):
pass
class ThirdScopedException(Exception):
pass
def scenario() -> bool:
if ...:
raise FirstScopedException("First Exception")
elif ...:
raise SecondScopedException("Second Exception")
elif ...:
raise ThirdScopedException("Third Exception")
return True
def main():
try:
scenario()
except (FirstScopedException, SecondScopedException, ThirdScopedException) as e:
print(f"Failed to process the function: {str(e)}")
finally:
# Clean Up
pass
main()
Прочитав исходный код вашей функции вы сразу узнаете какие исключения она может выдать и вы сможете их корректно обработать.
Вы так же можете создать базовый класс чтобы наследовать исключения от него и обрабатывать абсолютно все исключения для вызванной функции в вашем проекте.
Использования try/except
как и контекст менеджер
гарантирует высвобождение ресурсов которые вы сможете сделать в finally
блоке (закрытие соединений, чтение файлов, etc).
Не бойтесь писать код, главное чтобы он был понятен вам и другим людям которые будут его в дальнейшем читать!
Дробите большую программу на маленькие части и делайте функции чище по возможности (но не до фанатизма).