Вы все еще делаете эти ошибки Python в 2022 году?

6 ошибок Python, которые нужно исправить, чтобы стать лучшим программистом

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

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

За более чем 5 лет написания кода на Python я постоянно узнавал новые вещи и практики, которые со временем сделали меня лучшим программистом. Есть много ошибок, на которых я научился, и я хочу поделиться некоторыми из них здесь, которые я хотел бы исправить намного раньше. Эти ошибки не приведут к синтаксическим ошибкам, но в конечном итоге приведут к логическим ошибкам или просто к плохому коду. Я не уклоняюсь от признания того, что я виновен в каждой из этих ошибок в прошлом, и мой старый код является свидетельством этого, но нужно узнать об этих вещах как можно скорее. Итак, поехали!

1. Использование импорта *

Вы только что начали проект по науке о данных и очень рады применить все новые приемы и инструменты Python, которые вы приобрели в своем проекте. Для точности вашей модели вы пишете from sklearn.metrics import * для всех интересных показателей оценки, которые может предложить библиотека. Вы только что сделали первую ошибку!

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

  • Вы загрязняете свое пространство имен, потому что оно импортирует все из модуля в пространство имен. Это занимает память и может привести к перезаписи, о которой вы не знали. Из-за этого функции и классы в вашем собственном пространстве имен могут конфликтовать с теми, которые вы определяете, или из других библиотек, что приводит к непредвиденным логическим ошибкам.
  • Это влияет на читабельность кода, потому что теперь определенные функции и переменные в вашем коде нельзя отследить до того места, откуда они появились. Это означает, что случайная функция sqrt() в вашем коде может быть из numpy, math или даже пользовательской функции, о которой вы понятия не имеете. Это также усложняет отладку.

Решение. Убедитесь, что вы всегда указываете, что и откуда вы импортируете. Пример показан ниже.

import secrets
import string
import re
from wsgiref.util import request_uri 
from http.client import responses
from rest_framework import viewsets, status
from rest_framework.response import Response
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.decorators import permission_classes

2. Использование заморозки пунктов для хранения требований

pip freeze — одна из самых популярных команд управления требованиями Python. Он часто используется для хранения требований вашего проекта в текстовых файлах. Он используется многими начинающими программистами Python для управления своими виртуальными средами. Тем не менее, он имеет целый набор проблем, включая циклические зависимости и контроль версий.

Я написал очень подробную статью о проблемах использования pip freeze и возможных решениях, которые вы можете использовать.



Прекратите использовать «заморозку пипсов для своих проектов на Python
Обсуждение того, почему заморозка пипсов не так крута, когда дело доходит до управления зависимостями Python в направлении datascience. ком»



Моя личная рекомендация - переключиться на pipreqs для решения этой проблемы.

3. Написание скриптов Python без Main

Поскольку Python — это язык сценариев, вы можете писать и выполнять его в режиме цикл чтения-оценки-печати (REPL). Например:

# test_function.py
def function1(): 
    print("Hello world") 
function1()

Этот фрагмент кода будет выполнять функцию, когда она вызывается из CLI с помощью команды python test_function.py. Однако теперь, если вы хотите импортировать ту же функцию в качестве модуля в другой файл, скажем, jupyter notebook , это то, что произойдет.

По сути, код внутри функции запускается автоматически при импорте функции. Это может быть нормально в случае простой функции, как описано выше, но если код содержит вычислительно ресурсоемкие задачи, код будет продолжать работать даже при импорте. Вот почему написание __main__ важно для сценариев Python.

# test_function.py
def function1(): 
    print("Hello world") 
function1()

# Define the __main__ script
if __name__ == '__main__': 
    
    # execute only if run as a script
    function1()

Приведенный выше код обеспечивает ту же функциональность с CLI, но не запускается при импорте как модуль, если только не запускается специально. (как показано ниже)

4. Использование оператора assert в качестве условия защиты

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

Однако есть большая оговорка — когда интерпретатор Python вызывается с флагом -O (оптимизация), операторы assert удаляются из байт-кода. Таким образом, если операторы assert используются для проверки в производственном коде, они вообще не будут выполняться. Это может привести к огромному количеству логических ошибок и уязвимостей в системе безопасности. Следовательно, мы должны использовать только assert statements внутри тестов. В производстве мы можем переключиться на AssertionError.

Incorrect: assert condition, message 
Correct method: 
if not condition: 
    raise AssertionError

5. Использование isinstance() и type() correctly

Есть много мест, где мы должны проверять тип данных или класс объекта в наших кодах на Python. Методы перехода для этого — type() и isinstance() . Оба они широко используются, и важно убедиться, что мы понимаем, где что использовать вместе с предостережениями.

Любой из двух методов можно использовать для проверки типа объекта в Python. Однако есть большая разница в том, что они проверяют. isinstance также проверяет наличие наследования, а type — нет. Это становится актуальным, когда вы проверяете производные классы. Взгляните на приведенный ниже пример:

В приведенном выше примере, когда мы используем type, тогда int и bool обрабатываются как разные типы данных, которыми они и являются, но когда мы используем isinstance, они обрабатываются как одинаковые, потому что bool фактически унаследован от int в Python.

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

6. Неправильное использование аргументов функции по умолчанию

Распространенное заблуждение (которое я тоже недавно прояснил) заключается в том, что аргументы по умолчанию, которые вы передаете функциям, будут сбрасываться до указанного значения по умолчанию каждый раз, когда функция вызывается. Посмотрите на этот пример.

def func(list1=[]):      # here l1 is a default argument set to []
    list1.append("Temp") 
    return list1

Давайте посмотрим, что произойдет, если мы вызовем func несколько раз.

Приведенный выше результат может вас шокировать, но это очень логичный результат. В Python значение по умолчанию для функции оценивается только один раз, когда функция определена. Каждый другой экземпляр вызова функции будет использовать первоначально определенное определение аргумента по умолчанию. Следовательно, list1 сначала оценивается как [], а затем каждый раз выполняется операция добавления к исходному списку.

Эта проблема возникает с изменяемыми типами данных, и способ исправить это — использовать none statement и оценить список внутри функции следующим образом.

def func(l1=None):      
    if l1 is None: 
        l1 = []
    l1.append("Temp") 
    return l1

Заключение

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

Вы также можете проверить некоторые другие вещи, которые я написал.