Написать пост

Способы «выстрелить себе в ногу» в Python

Аватарка пользователя Елена Капаца

И остаться при всех конечностях. Разобрали шесть типичных ошибок новичков с примерами кода и нашли решение каждой.

Обложка поста Способы «выстрелить себе в ногу» в Python

«Выстрелить себе в ногу» означает следующее: «Можно написать команду или конструкцию, которая сломает нормальное поведение программы или системы (или будет выполняться совершенно не так, как предполагалось), и при этом компилятор/интерпретатор это съест” и не остановит исполнение кода». Иными словами, это возможность навредить себе необдуманными действиями.

Когда создатель C++ Бьярне Страуструп впервые употребил такое сравнение по отношению к C/C++, это породило целый шквал шуток и про другие ЯП, в том числе Python:

«Python — это двуствольный обрез v.2/3, причем за раз палит только одной половиной. Никогда не угадаешь, какой. Вы пытаетесь “выстрелить себе в ногу”, но то и дело попадаете в пробелы между пальцами» (полный список языков с шутками на neolurk.org)

Хоть последняя часть звучит так, словно ошибиться трудно, это вполне возможно. Если вы недавно приступили к программированию, то скорее всего, пока это делаете. Предлагаю вместе разобраться с видами «ранений» и сократить ошибки на старте.

Непрозрачное именование

Нейминг является важным аспектом разработки по нескольким причинам:

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

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

			def check():
	...
		

Лучше добавить конкретики:

			def check_game_completion():
	...
		

ВРЕЗКА. Если вы хотите познакомиться с продвинутой логикой именования объектов в Python, обратитесь к этой статье.

Внешние модули вместо встроенных

Использование «родных» решений в Python имеет несколько преимуществ:

  • Стабильность и надежность: встроенные модули тщательно тестируются и поддерживаются разработчиками. Они реже создают проблемы и не требуют дополнительных усилий при установке.
  • Переносимость: встроенные модули являются частью стандартной библиотеки Python. То есть они поставляются вместе с интерпретатором. Это гарантирует кроссплатформенность: не нудно устанавливать дополнительные пакеты. Часто при работе в Jupyter Notebook / Kaggle нас замедляют ошибки импорта сторонних решений.
  • Встроенные модули часто реализованы на языке Cи. Это обеспечивает повышенную производительность (см. Python vs. C). Исключение: автор стороннего решения указал, что оно написано на Си или другом низкоуровневом языке.
  • Проще поддержка: при использовании только встроенных модулей меньше проблем с конфликтами зависимостей.

Не проверять и не приводить типы

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

Допустим, мы просим пользователя ввести число:

			number = input("Введите число: ")
result = number + 5
print(result)
		

Юзер вводит 10, однако, input() по умолчанию возвращает строку, поэтому дальнейшая попытка сложить строку с числом (’10’ + 5) приведет к ошибке. Для исправления стоит привести вводимое значение к целочисленному типу (int):

			number = int(input("Введите число: "))  
result = number + 5
print(result)
		

Не ожидать исключений

Отсутствие try – except в моей практике часто приводило к тому, что приходилось «скакать» из проекта в проект, чтобы оперативно отладить упавший скрипт. Это вредное следствие истончало драгоценную способность концентрироваться в первые годы программирования. Однако поначалу не всегда ясно, каких именно ошибок ждать и куда внедрять эту конструкцию:

			try:
    # некоторый код
except Exception as e:
    # необработанное исключение
		

Здесь облегчит положение знание типов ошибок. Хоть падения часто бывают непредсказуемыми, некоторые можно предположить. Кто бы показал мне это древо ошибок в первый год с Python! Может, огромная фрустрация от первых неудачных попыток была бы поменьше:

Способы «выстрелить себе в ногу» в Python 1

Иерархия ошибок в Python

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

Отсутствие тестов

Лучше создать плохие немногочисленные тесты, чем делать релиз без них вообще. Если нет такого навыка, стоит начать с чего-то простого, и постепенно вводить улучшения.

Хороший гайд по unittest / pytest можно найти по ссылке.

ВРЕЗКА. Интересно, почему же тогда на курсах Data Science так ловко минуют/сокращают эту тему? Наверное, дело в том, что модели на курсах получаются учебные, в продакшен они не выводятся, а значит, студенты обойдутся и без навыков проверки качества. Это вредная привычка онлайн-школ создает плохо понимающих тестирование. Если вы решили учиться по этой специальности, возьмите дополнительный небольшой курс на 2-3 часа на эту тему.

Не закрывать файлы и ресурсы

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

			# Откроем
fo = open("foo.txt", "wb")
print"Name of the file: ", fo.name
# Закроем
fo.close()
		

Заключение

Говорят, что лучший способ перестать «стрелять себе в ногу» — наошибаться поначалу. То есть увидеть, как неясный нейминг замедляет отладку, или устать от падающих программ без try – except. Отрицательное подкрепление – жестокий, но хороший учитель.

Я уверена, что с появлением опыта и развитием навыков вероятность таких «ранений» у вас будет снижаться. Порой в условиях информационной перегрузки только это и остается: дождаться, пока мозг усвоит большой объем информации, и потихоньку оптимизировать код в лучших традициях PEP.

Следите за новыми постами
Следите за новыми постами по любимым темам
1К открытий2К показов