Читая плохой код, вы можете узнать больше, чем хороший код
Я кодирую на Python более шести лет, и до сих пор я все еще изучаю новые концепции и передовые методы для улучшения качества кода.
Когда я только начинал, понять, как что-то делать, было непросто: мне пришлось выучить это на собственном горьком опыте.
В этом посте я решил составить список из 18 антипаттернов и худших практик Python, о которых я хотел бы знать раньше: это может сэкономить вам время и ускорить отладку ваших проектов.
Этот список основан на обсуждениях с коллегами-разработчиками Python, экспертами по программированию и долгих погружениях в темы Reddit.
Но это не исчерпывающий список: если вы хотите углубиться в эту тему (интересная, клянусь, ) Я привел несколько ссылок в конце.
Давай посмотрим сейчас 🚀
0-прежде чем начать, что за антипаттерн?
Антишаблоны - это определенные шаблоны в разработке программного обеспечения, которые считаются плохой практикой программирования.
В отличие от шаблонов проектирования, которые представляют собой общие подходы к общим проблемам, которые были формализованы и обычно считаются хорошей практикой разработки, анти-шаблоны являются противоположными и нежелательными.
Антишаблоны делают код трудным для чтения, сложным в обслуживании, медленным, чрезмерно сложным, нестабильным, подверженным ошибкам и с потенциальными проблемами безопасности.
Введение антипаттернов происходит по многим причинам:
- отсутствие проверки кода
- готовность опробовать "крутые" вещи, когда простые вещи могут помочь
- не использовать правильные инструменты (линтеры кода и средства форматирования в соответствии с соглашениями PEP8, генераторы строк документации, IDE, поддерживающие автозаполнение, и многие другие)
- или просто не зная лучшей альтернативы, что нормально, если вы учитесь и растете
Антипаттерны можно разделить на одну или несколько из следующих категорий:
- Корректность: анти-шаблоны, которые буквально сломают ваш код или заставят его делать неправильные вещи.
- Ремонтопригодность: антишаблоны, затрудняющие поддержку или расширение вашего кода.
- Читаемость. Антишаблоны, затрудняющие чтение или понимание вашего кода.
- Производительность: антишаблоны, которые излишне замедляют ваш код.
- Безопасность: защита от шаблонов, создающих угрозу безопасности вашей программы.
Давайте теперь посмотрим на этот список из 18 антипаттернов. Некоторые из них подпадают под одну или несколько категорий.
1 - Использование неявных имен переменных
Имена переменных всегда должны быть описательными, чтобы обеспечивать минимальный контекст: имя переменной должно словами сообщать вам, что обозначает переменная.
Это упрощает понимание кода другими разработчиками и упрощает отладку для вас.
СОВЕТ 👉: не бойтесь использовать длинные имена переменных для наглядности: современные IDE, такие как VSCode и Pycharm, обеспечивают быстрое автозаполнение.
2 - Игнорирование комментариев
Недокументированный код - это кошмар. Вот люди, которые могут жаловаться на это:
- через 6 месяцев, когда вы забудете, зачем вы написали эту строчку кода
- любой ваш коллега, который возьмет на себя проект
Код всегда должен четко указывать, что он делает, а комментарии должны разъяснять, почему вы это делаете. В то же время, комментируя свой код, будьте лаконичны. Если ваш код не требует пояснений, комментарии не нужны.
СОВЕТ 👉: если вы используете VSCode, вы можете ускорить создание строк документации с помощью этого расширения, которое автоматически генерирует шаблон комментария для ваших классов и функций.
3 - Забыть обновить комментарии
Комментарии, противоречащие коду, хуже, чем их отсутствие.
Это происходит чаще, чем вы думаете: когда вы спешите и вам нужно исправить неработающий производственный код, вы сделаете это, не найдя времени на обновление старых комментариев.
Устаревший комментарий вводит в заблуждение всех, кто работает над кодом.
Всегда есть время обновить комментарии.
4 - Использование CamelCase в именах функций
Это больше похоже на соглашение: руководство по стилю PEP 8 рекомендует, чтобы имена функций всегда были в нижнем регистре, а слова разделялись символами подчеркивания.
5 - Отсутствие итерации непосредственно по элементам итератора
Это довольно распространенный антипаттерн. Вам не обязательно перебирать индексы элементов в итераторе, если они вам не нужны. Вы можете выполнять итерацию непосредственно по элементам.
Это делает ваш код более питоническим.
6 - Не использовать enumerate, когда вам нужен элемент и его индекс одновременно
Если вам нужно получить доступ к элементу и его индексу одновременно при повторении итератора, используйте enumerate
.
7 - Не использовать zip для перебора пар списков
zip
- полезная встроенная функция, которая позволяет создавать список кортежей из двух итераторов. первый элемент каждого кортежа поступает от первого итератора, а второй элемент - от второго итератора.
zip
может быть полезен, если вы хотите перебрать два или более итератора одновременно.
8 - Не использовать диспетчер контекста при чтении или записи файлов
Когда вы используете open
без диспетчера контекста и перед закрытием файла возникает какое-то исключение (закрытие файла - это то, что вы должны помнить, открывая файл таким образом), могут возникнуть проблемы с памятью, и файл может быть поврежден в процессе.
Когда вы используете with
для открытия файла и возникает исключение, Python гарантирует, что файл закрыт.
9 - Использование in, чтобы проверить, содержится ли элемент в (большом) списке
Проверка наличия элемента в списке с помощью оператора in может быть медленной для больших списков. Вместо этого рассмотрите возможность использования набора или пополам.
Вот сравнение трех методов:
→ источник: StackOverflow
10 - Передача в функции изменяемых аргументов по умолчанию (т.е. пустой список)
Вот забавная вещь в Python, которая может приводить к скрытым ошибкам и скрытым ошибкам: аргументы по умолчанию оцениваются один раз, когда функция определена, а не каждый раз, когда функция вызывается.
Это означает, что если вы используете изменяемый аргумент по умолчанию (например, список) и измените его, вы также измените этот объект для всех будущих вызовов функции.
Чтобы избежать этой проблемы, вы можете установить для аргумента по умолчанию to
значение None:
- если функция с вызывается несколько раз с
to
, установленным на None, создайте новый пустой список и каждый раз добавляйте к нему элемент - когда вы передаете список в
to
, вы добавляете к нему элемент. Поскольку это не аргумент функции по умолчанию, это работает хорошо.
11 - Возврат разных типов в одной функции
При попытке обработать специальные пользовательские вводы, которые могут вызывать ошибки, вы можете иногда вводить None в качестве вывода. Это делает ваш код непоследовательным, поскольку ваша функция теперь возвращает как минимум два типа: исходный тип, который вы планировали, и тип NoneType.
Это затрудняет последующее тестирование и отладку.
Вместо того, чтобы возвращать None, вы можете вызвать ошибку, а затем отловить ее.
12.Использование циклов while, когда простые циклы for помогут
Вам не нужно использовать цикл while, если вы заранее знаете количество итераций.
13 - Использование составных и вложенных операторов if
Сложенные и вложенные операторы if затрудняют соблюдение логики кода.
Вместо условий вложения их можно комбинировать с логическими операторами.
14 - Использование глобальных переменных
Избегайте глобальных переменных, таких как чума. Они являются источником многих ошибок. К ним можно получить одновременный доступ из нескольких разделов программы, что может привести к ошибкам.
Типичная ошибка, возникающая при использовании глобальных переменных, - это когда функция получает доступ к своим значениям до того, как другая нуждается в правильном обновлении.
15 - Не использовать get () для возврата значений по умолчанию из словаря
Когда вы используете get
, python проверяет, существует ли указанный ключ в словаре. Если да, то get()
возвращает значение этого ключа. Если ключ не существует, get()
возвращает значение, указанное во втором аргументе.
16. Использование блоков try / except, которые не обрабатывают исключения осмысленно
Следует избегать использования блока try / except и игнорирования исключения путем его передачи (например).
17 - гордо печатать: из модуля импорта *
Импорт всегда должен быть конкретным. Импорт * из модуля - очень плохая практика, которая загрязняет пространство имен.
18 - Все переосмыслили
Вам не всегда нужны занятия. Простые функции могут быть очень полезными.
Классы часто имеют методы, которые являются функциями, связанными с определенным классом, и делают вещи, связанные с тем, чем является класс, но если все, что вам нужно, это что-то делать, функция - это все, что вам нужно.
По сути, класс - это способ группировки функций (как методов) и данных (как свойств) в логическую единицу, вращающуюся вокруг определенного рода вещей. Если вам не нужна такая группировка, не нужно создавать класс.
Спасибо за чтение 🙏
Надеюсь, это было вам полезно. Если вы знаете другие популярные антипаттерны Python, не стесняйтесь указывать мне на них в комментариях.
Удачного взлома, до следующего раза 👋
Ресурсы:
- Https://docs.quantifiedcode.com/python-anti-patterns/index.html
- Https://deepsource.io/blog/8-new-python-antipatterns/
- Https://github.com/quantifiedcode/python-anti-patterns
- Https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments
- Https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments
- Https://towardsdatascience.com/data-scientists-your-variable-names-are-awful-heres-how-to-fix-them-89053d2855b