Принцип EAFP в Python, работа с исключениями в Python. Применение принципов Zen of Python
HTML-код
- Опубликовано: 21 авг 2020
- Мой курс «Хардкорная веб-разработка» - course.to.digital
Книжный клуб Ботаним!, где мы читаем хорошие ИТ-книги: botanim.to.digital/
Telegram: t0digital.t.me
Сказать спасибо за это видео можно здесь - boosty.to/digitalize.team
EAFP - важный принцип, позволяющий писать более «pythonic» код. EAFP расшифровывается как Easier to ask for forgiveness than permission, а его антипод LBYL - Look before you leap. Поговорим о разнице и о том, почему именно EAFP выбран разработчиками Python как правильный способ проектирования приложений.
/****************** about ******************/
Меня зовут Алексей Голобурдин, я программирую с 2004 года и на этом канале делюсь своим опытом. Я основатель и руководитель компаний:
- Диджитализируй digitalize.team, разрабатываем сложные IT системы для бизнеса;
- Salesbeat salesbeat.pro, комплексный модуль доставки для интернет магазинов.
Если у вас есть проект на разработку, пишите нам на hi@digitalize.team.
С другими предложениями, а также если вам нужна одна или несколько индивидуальных консультаций/уроков по разработке (3000 руб/час), пишите мне на alexey@salesbeat.pro.
Telegram канал - t.me/t0digital
ВК - digitalize.team
RuTube - rutube.ru/channel/24802975/ab...
Дзен - dzen.ru/id/6235d32cb64df01e6e...
Наверное самый полезный канал по пайтону на русскоязычном ютубе
Спасибооо!
Ещё Олег Молчанов неплохо объяснял (давно у него роликов не было). И автор этого канала, на котором мы сейчас, безусловно - молодец!
@@user-oi1zl6de8i Да, как раз когда писал, Олег был на уме как и диджитализируй)
@@kalik54 Да, эти товарищи вносят существенный вклад в развитие python-сообщества в России и русскоговорящих странах.
@@user-oi1zl6de8i +. скорее он бы вернулся(
Отличный контент. Хочется увидеть серию уроков по aiohttp, поддержите лайками чтобы поднять в топ.
starlette и fastapi интереснее
@@rishatsharafiev aiohttp и asyncio интереснее
@@rishatsharafiev Асинхрон - концепт современного кодинга, это прям надо. Это есть в C++, C#, Python, Rust и вообще везде (правда, Java немного страдает), это надо изучать не только питоноидам.
А мне бы Sanic, сколько людей столько мнений))
@@MegaFeel1 хорошо, что фреймворков меньше))
Спасибо за контент Алексей. Мне нравится, что вы уделяете внимание картинке и звуку.
Предлагаю снять ролик о том, как дебажить на пайчарме. Было бы интересно.
Можно ли еще видео как до этого было, часовое по django, очень зашел формат, только по django REST)
Алексей, спасибо большое за вашу работу.
Просто и понятно!
Лайк однозначно! Качество контента растёт на глазах!
Приятно слушать, смотреть и учиться. И все без воды. Спасибо!
Шикарный выпуск. Такие ньюансы очень полезны. Даёшь больше best practice примеров из Python и Django!
Спасибо! Как всегда отличная подача и полезная информация!
классно, что говоришь быстро, не нужно ускорять видео)))
Спасибо ,как всегда огонь инфа!
Пару дней назад нашел ваш канал и уже пересмотрел больше половины видео. Рассказывает обо всем очень доступно и интересно! Из тех, что попадались на русском RUclips, наверно, первый канал, который не рассчитан на абсолютно начинающих и не рассказывает, как "Выучить Python за час" или что-то из этой серии. Удачи в развитии!
Как всегда отличное и полезное объяснение по делу! Спасибо!
Спасибо за выпуск. Хорошо прояснил официальные подходы !) Круто!
Лаконично и доступно! Пять балов за изложение мысли!
блин, это один из лучших каналов по программированию, от души за все советы))
спасибооо!
суперская подача инфы, больше видео как надо и как не надо !)))
серьезно, такая мелочь, но очень полезная инфа, оказывается данные подходы еще и именуются как-то, сколько раз с другими программистами спорили как правильно, как нет (не только питон), теперь же все по полочкам, спасибо за действительно полезный ролик, развития каналу
Алексей, круто! Спасибо большое) Очень бы хотелось побольше подобных видео о лучших практиках
Хороший ролик, спасибо :)
Очень полезное видео! Спасибо!
А что насчет скорости выполнений? Читал, что try/except выполняются медленнее, чем условия, поэтому в своём коде обычно их не использую.
@@avazart614 и не про чистоту кода, по всей видимости
Спасибо за годноту, а когда будут выпуски про aiohttp?
Скоро будут!
Было очень полезно! Спасибо!
офигенное видео, спасибо!
Неоднократно задавался вопросом, использовать условия или исключения. А, оказывается, все так просто. Теперь смогу сделать свой код лучше. Благодарю.
Продвигаем годноту в массы
Очень давно так делаю, теперь просто знаю как это называется )))
Спасибо за контент!
Спасибо мужик!
У тебя много что узнаю. Только уважение к тебе.
Спасибо!
Круто снял!
Круто и очень полезно! Дьявол скрывается в деталях)
100%!
Добрый Комент!
"Да прибудет с вами сила" - это уже устраешая фраза. Надо говорить: "Таков путь!" ;)
Спасибо за кусочек питонячей дисциплины.
Спасибо за контент! Нужно скинуть в чаи группы, им должно понравиться)
В первом примере LBYL подхода, должен быть еще else с выводом текста об не найденном ключе))
Спасибо за Python контент!
Рад, что полезно:)
Полезное видео. Больше подобных)
Спасибо!
Отличный контент. Круто прогрессировал последнее время
Спасибо! А что бы вы отметили, что за последнее время стало лучше на ваш взгяд? Темы видео, подача, картинка, звук, ещё что-то? Полезно будет знать.
Спасибо!
Просто и грамотно. Пасиб
Вообще, слышал такое мнение: если знаешь что может пойти не так - используй if-else, так как исключение в питоне довольно медленные. Сами же исключения используются для исключительных ситуаций, когда что то идет не так из за внешних факторов. То есть в примере с диктом я бы использовал if else, в случае сетевого взаимодействия или дискового - уже исключения.
Да чем всех dict.get( ) не устраивает?
Я тоже за подход, что легче просить прощения, чем разрешение. Спасибо за прекрасный материал.
Спасибо, лайк!
Круто!
Спасибо! Лайк! От других программистов слышал обратное, try/except использовать если по-другому нельзя, т.к. дорогая операция. Хотя тесты которые я видел показывали, что дорогой становится при частой ловле исключений.
Try/except дешёвый, если не генерится исключение, а генериться оно должно редко, это ведь исключительная ситуация
Отличное видео! Алексей, когда же будет запуск обучения?
Скоро-скоро!
Спасибо!
Хотел спросить. Будут ли видео по Flask? На мой взгляд это очень показательный фреймворк, т.к. есть большая свобода действия.
Отлично рассказываете! У вас есть видео об ООП в python? Если нет, то было бы круто от вас услышать базовые вещи об этом! Спасибо за ваш труд!
Все в видео очень лаконично и ясно, будто хороший код на питоне. :)
Вопрос, почему часто читаю в книгах по computer science, что использование исключений является не очень хорошей практикой программирования? И даже при создании своего языка Goland авторы, например, решили отказаться от поддержки исключений. Чем это вызвано?
Потому что исключения начинают использоваться не по назначению, они разворачивают стек вызовов и добавляют оверхед по производительности и потребляемой памяти только ради того, что бы программисты смогли снова вернуться во времена оператора goto. Исключения добавляют неясности в кодоввю базу и надо усердно курить мануалы что бы понять может ли какая то функция прокинуть ошибкуи и в каких ситуациях
Огонь! Полностью согласен!!!
Спасибо! Как раз вот пишу код и думаю об этом. Очень кстати! Было бы супер как-нибудь поглядеть на код модульных тестов, которые в том числе проверяют такие ветки с прерываниями, чтобы велосипед не изобретать.
Классный формат, рассказывать про такие маленькие фичи. И понимание зена возрастает, и код лучше будет
Как интересно, а я всеми силами старался избежать try except, приму к сведению, спасибо.
Я так же)
Оно тоже затуманивает логику как и if на каждом шагу. Если except на каждом шагу то это не лучше а даже медленнее
А если не на каждом шагу проверка нужна то можно и без if'а, и без локальных except (только большой "всё-ловящий" try/except)
Блин, почти не использовал try/except в своем коде, везде пихал if/else. А после этого видео, буду писать правильно. Спасибо!!!
Полезная инфа
Пасиб)
А я вместо кучи ифов пользуюсь свичкейзом через метод словаря .get(key, default=None). Получается очень красиво и читаемо!
Хороший ролик, лайк!
Дааа, .get очень удобный метод, тоже часто использую!
Спасибо!
God bless you!
Злой комментарий)))
Спасибо за видео!
В примере не совсем понятно, какое требование стоит в ТЗ. Т.к. в зависимости от этого может быть и If лучше, если ключа у нас действительно может не быть в словаре.
Почему-то вы изначально за аксиому взяли, что нормальное поведение - это когда ключ есть. А если это не так? То нормальным будет уже if...
Да и к тому же пример с if не полон, если добавить туда else с выводом той же ошибки, то разница уже не так очевидна.
И почему во втором примере нельзя написать так?
try:
with open(tmp_file) as f:
print(f.read())
except IOError as e:
print("Error")
наверно что бы можно было понять где падает open а где read. Но это как то нелепо описывать условную логику через эксепшены.
Обожаю свои программы заворачивать снизу доверху в except Exception! Правда я обычно пишу сервероподобный софт, а такие вещи делаю, чтобы весь процесс не упал из-за пропущёной запятой в тридевятой вьюхе.
Когда будет урок про git? В первых видео обещали, но так и не разобрали данную тему :(
Сейчас на работе пришлось самому разбираться. Очень жалею что не юзал это раньше.
Я писал в 2013м статью по базовому гиту - goloburdin.blogspot.com/2013/11/git-bitbucket-20.html
Видео тоже планирую, просто хочется сделать что-то глубже, чем просто commit/pull/push/merge/checkout
Как вас вообще на работу взяли)
Огромное спасибо за видео, хоть пока мне и без толку данная информация (не тот уровень скила), но прям от видео веет дружеским наставничеством.
Было бы кстати неплохо посмотреть ваш подход к началу проекта, с чего стоит начинать писать.
P.S. А mailto:mailto: так и не исправили :-)
Ээээ...круто)
Есть мнение, что содержимое try выполняется 2 раза. 1й раз на пробу брода, 2й раз на переход брода. Поэтому если много проходов по траю - будет растрата ресурсов
Добрый коммент=)
спасибо:)
В защиту LBYL скажу, что сейчас в python есть довольно много инструментов, с помощью которых можно делать подобные проверки красиво и прозрачно. К примеру, библиотека trafaret. Всегда её использую при обработке тела запроса клиента на сервер.
Что там по курсу??
Анонсируйте подалуйста примерную дату курсов
Было бы интересно от вас послушать как SOLID применяются в Python. Думаю тема достаточно непростая и очень важная!
github.com/heykarimoff/solid.python
Хороший Рол вкусный! Хорошо зашёл) Кто такие Катаны? «здорова Катаны»
Думаю, что имеется в виду кОтаны. Ну т.е. мальчики выросшие из котяток... 😃
А че) очень полезно)
Очень, очень не нравятся блоки try except в коде.
Единственный момент, когда могу пойти на компромисс - это интеграции - различные запросы. Но при возможности, закидал бы камнями разрабов в момент разработки либ, методы которых бросают исключения (привет request timeout error).
Мало того, что сами блоки занимают много места и делают код менее читабельным, так некоторые просто напишут "except: pass" и спят спокойно.
Да и в целом... все ошибки не переловишь и этот домик из "except ...: ..." может расти и расти.
И это одна из причин, почему перехожу потихоньку на Golang и пишу не dictionary[key], а dictionary.get(key) и обрабатываю None.
С файлом пример понравился, но будем надеиться, что, во время работы с ним одного потока, другой не делает критических изменений с флогом "w+".
Последний фрагмент кода нужно было написать так, чтобы *try-except* был внутри функции?
try:
something = some_dict["key"]
except KeyError:
# do some stuff
pass
else:
some_func(something)
Напр, так
я, в последнее время перешел assert'ы:
from assertpy import assert_that
some_dict = {}
assert_that(some_dict, 'Dictionary').contains_key('key')
AssertionError: [Dictionary] Expected to contain key , but did not.
Да, не так оптимально, да, асерты не совсем про валидацию, но, на объёмах - работает лучше, чем куча try/except, в плане качества кода, читабельности. Где нужно оптимальнее - конечно меньше валидаций.
Разработчки библиотеки сказал, что я пользуюсь defensive assertions, что бы это не значило :).
@Вячеслав Украинцев так и есть. Поэтому они не про вадидацию. Но тут сторонняя библиотека, ну и асерты, прямо по назначению, я что-то и не использовал никогда.
Не является ли в случае со словарями использование метода get более предпочтительным вариантом получения значения по ключу? Или этот метод по сути и есть отображение EAFP?
если задача просто получить значение по ключу, а если ключа такого в словаре нет, то взять некоторое дефолтное значение - то да, метод get предпочтительнее. EAFP он не только про словари, это общий принцип, просто на словарях его часто показывают. В видео есть пример с открытием файла и возможным состоянием гонки без EAFP
@@t0digital Спасибо за ответ! :)
С меня предоставляется коммент за годный контент! Жаль, что задонатить не могу(
А точно стоит ронять весь код ради ключа/файла?
В логи записать ERROR недостаточно будет?
Ронять весь код не надо, если это не фатальная проблема, с которой невозможно продолжать. Обработка исключений и eafp и позволяет не убивать программу.
не знаю что написать но напишу)
4:56 у вас при исключении файл не закроется.
И кстати конструкция with закрывает файл после действий, но здесь это не поможет.
А почему нет блока else, он нужен чтобы сообщить что ключа нет! )
А если обернуть весь код блоком трай/эксепт, чисто в целях отлова неожиданных ошибок?
Можно. Только получите эту неожиданную ошибку и надо неожиданно с ней разбираться.
Тут искусственные примеры были и в реальности все сложнее. И проще. Нет одного такого EAFP на всем случаи жизни.
if конечно лучше, но просто не всегда надо или придется этот if включать
Я не спрошу "что такое принцип EAFP", я спрошу "кто такие котаны или катаны"
Те кто отключают интернет во время деплоя))
я так и не понял объясните еще раз- нужно всегда проверять есть ли ключ в структуре данных и потом его применять?
Всегда не надо, надо, когда есть вероятность, что ключа нет в словаре. Когда что-то может пойти не так в программе, на это надо заложиться
@@t0digital вот на фронтэнде так всегда приходится делать потому сервера часто падают и поэтому в большинстве случаев так приходится делать
А в плане ресурсов что дешевле if или try/except? Что-то мне подсказывает, что первая конструкция...
try/except плюс-минус такой же дешевый, как и if, если не возбуждается исключение. Когда оно возбуждается - это дороже, чем if. Но соль в том, что исключение оно на то и исключение, что должно возбуждаться редко.
@@t0digital Спасибо за ответ!
Да, но только конструкция try except потребляет больше ресурсов чем if, python для блока try копируются все переменные и уже с копиями выполняются операции из блока try чтобы не запороть основной цикл программы и не испортить переменные если код в try свалиться в исключение и продеться откатывать
добрый комментарий
добрый комментарий
добрый комментарий
Хахаах, спасибооо!
А я думал, что try/except как раз для того, чтобы минимизировать ветвления и обработчики исключений, оставив один обработчик по умолчанию на самом верхнем уровне.
try/except вызывает отдельный стек Python в блоке try , по этому он будет медленнее. По этому с точки зрения языка вызов if 'key' in dict будет быстрее. if 'key' in dict и dict["key"] не вызывает два раза поиск ключа, а один раз, так как в стеке индекса он будет первый и пайтон всего лишь сравнит тот ли ключ.
Исключения не медленнее if/else. Исключение медленнее только если оно происходит, но оно должно происходить редко, что следует даже из названия, исключение создано для исключительных ситуаций. docs.python.org/3/faq/design.html#how-fast-are-exceptions
@@t0digital Да глянул исходники для try если ключ проверяют вызывают _PyObject_GetDictPtr , для OS ещё не придумали как сделать try быстрее.
@@t0digital Ещё работает для Tuple
Вроде сишники (особенно эмбеддщики) говорят, что исключения какие-то дорогие и слишком медленные из-за того, что там какие-то манипуляции со стэком происходят. Это правда?
4:44 а разве не лучше считывать тоже в блоке try? Вдруг во время чтения что-то произойдёт.
А, точно после открытия файла для чтения файл полностью принадлежит процессу и ошибки быть не может... поэтому покрасивше будет выделить чтение в блок else
Злой писать не охота, а вот добрый, пожалуй, оставлю. У меня такая проблема. Год назад начал изучать Питона вообще с нуля. С такого уровня, что вообще первый раз открыл cmd. Сейчас пишу программы для своего бизнеса, но у меня нет развития, потому что имеющиеся знания покрывают потребности моего дела. Я понимаю, что с таким уровнем ни в какую компанию не попадёшь, а хотелось бы связать себя с профессией программиста. Прямо беда. Хочу развиваться, но вместо этого бег на месте.
1. try except сложнее чем использование if key in, в читабельности для человека, из за количества возможных отрицательных срабатываний, которые спрятаны в исключениях. И if является более явным и однозначно трактуемым, нежели exception.
2. Исключения крайне ресурсоемки, и программирование на них, если можно обойтись без них, это табу. В процессе, появления исключения, в питоне собирается информация о нем, что требует много ресурсов, и останавливает поток исполнения. Такие места можно заддосить.
3. Ошибки лучше оформлять
if key not in data:
raise Exception('исчерпывающее описание данной ситуации')
нежели то что вы привели в пример. Ваш пример можно часами трактовать, а какую ситуация для чего разраб покрыл этим exception.
Исключение такие же дешёвые, как if, если не возникает исключения, а возникать они должны редко исходя даже из названия. Что if более читаем, чем except - нет же. В исключении явно понятно, какая логика нормальна, какая исключительна, в if else обе ветки равнозначны и без контекста, без коментов это непонятно. Райзить Exception вместо KeyError или IndexError - не надо.
@@t0digital
1. Style
docs.python.org/3.8/faq/design.html#how-fast-are-exceptions
2. Performance
paltman.com/try-except-performance-in-python-a-simple-test/
3.
- Как в коде, который покрыт несколькими слоями try except finally, излишние try, усложняет структуру кода, доп отступами от которых не избавиться.
- Две строки, лучше чем четыре.
- Как быть здесь? На каком ключе споткнулись?
try:
value = data['key1']['key2']
except IndexError:
pass
- может все же вот так понятней?
if 'key1' not in data:
raise Exception('исчерпывающий ответ что пошло не так')
исполнение продолжилось.
- к какому жесткачу, приводит неосторожное использование.
try:
value = function()
except Exception:
pass
- трактовки.
Что можно ожидать от if key in data ?
Наверно, проверку вхождения, в массив, в строку или есть ли ключ в hashmap, зависит от типа данных data.
Что можно ожидать от try except. Очень много всего, особенно когда обернута функция, и глубину вызовов внутри этой функции не видно, и на любом этапе может произойти исключение, которое этот перехват скроет. А бывает и приведет к некорректному исполненbю алгоритма.
- нарушение логики.
С исключениями, мы предпочитаем сначала наступить в кучу навоза, а потом принимать решение. А проще, посмотреть прежде чем наступать нет ли там кучу с помощью if.
Что на итог:
Эту конструкцию, опытный разработчик назовет вкусовщиной. Я же против этих конструкций, т.к. мы не все опытные и знаем все подводные камни и отдаем себе отчет в них, и суем их всюду.
И это приводит к страшным поломкам. Чего не случится, если бы использовали if.
Денис Борисов от software enginering
почему?
Зачем вы сделали бейсбольный мячик своим крестражем?
В 1с использование такой конструкции считается плохим тоном.
Значит программист плохо учел возможные варианты, раз у него что-то может вызвать исключение.
1C сам по себе считается плохим тоном.
P.S. Ладно, шутка
@@user-dv9fk1hd3s давай напишем систему лучше) Аналогов я не нашел, ниша свободна.
Не шутка)
Аригато козаимасу:)
Как можно сравнивать разный функционал? Если вместо каждого if использовать try except то не только сложно будет читать, но и выполняться такая программа будет намного дольше.
Так и не предлагается везде заменить if на try/except
А как же быстродействие?
try/except быстр, когда не генерится исключение, а генериться оно должно редко