Как писать чистый код на Python
Python — один из наиболее элегантных и чистых языков программирования. Но красивый и чистый синтаксис не означает чистый код. И не избавляет разработчиков от необходимости изучать наилучшие приемы и шаблоны проектирования.
Что такое чистый код?
Процитируем Бьерна Страуструпа, создателя языка C++. Он дал очень четкое определение того, что можно считать чистым кодом.
«Я хочу, чтобы мой код был красивым и эффективным. Логика должна быть понятной — так багам будет сложнее спрятаться. Зависимостей должно быть как можно меньше — это облегчает поддержку. Обработка ошибок должна выполняться согласно определенной стратегии. А производительность должна быть приближена к оптимальной — чтобы не соблазнять людей заняться непринципиальными оптимизациями, которые могли бы запутать код. Чистый код делает что-то одно, и делает это хорошо».
Из этой цитаты мы можем выбрать несколько отличительных признаков чистого кода:
- Сфокусированность. Каждая функция, класс или модуль выполняют какую-то одну задачу, причем хорошо.
- Читабельность. Как сказал Грэйди Буч, автор книги «Object-Oriented Analysis and Design with Applications», чистый код читается, как хорошо написанная проза.
- Легкость отладки.
- Легкость поддержки. Если код чистый, другие разработчики без проблем смогут его читать и улучшать.
- Высокая производительность.
Конечно, разработчики вольны писать код так, как им нравится. Нет такого закона, который обязывал бы их писать исключительно чистый код. Но когда код написан плохо, это способствует накоплению технического долга и может повлечь за собой негативные последствия для компании. А это солидная причина писать код как можно лучше.
В этой статье мы рассмотрим несколько советов, как писать чистый код на Python.
Чистый код на Python
Имена
Соглашения об именах — один из самых полезных и важных залогов написания чистого кода. Обдумывая, как назвать переменные, функции, классы и т. д., выбирайте осмысленные имена, раскрывающие ваши намерения. Это предполагает, что следует отдавать предпочтение длинным и описательным именам.
Используйте длинные описательные имена, которые будет легко читать. Это избавит вас от необходимости писать лишние комментарии.
# Не рекомендуется # Переменная au - это число активных пользователей au = 105 # Рекомендуется total_active_users = 105
Имена должны раскрывать ваши намерения. Читая ваш код, другой разработчик должен по имени переменной понимать, что в ней хранится.
# Не рекомендуется c = [“UK”, “USA”, “UAE”] for x in c: print(x) # Рекомендуется cities = [“UK”, “USA”, “UAE”] for city in cities: print(city)
Избегайте непонятных сокращений. Лучше пусть имя будет длинным, но понятным, чем коротким и при этом неоднозначным.
# Не рекомендуется fn = 'John' Ln = ‘Doe’ cre_tmstp = 1621535852 # Рекомендуется first_name = ‘JOhn’ Las_name = ‘Doe’ creation_timestamp = 1621535852
Используйте один и тот же набор слов. Непоследовательность будет путать читателя. Это касается не только имен переменных, файлов, функций, но даже и структуры директорий.
# Не рекомендуется client_first_name = ‘John’ customer_last_name = ‘Doe; # Рекомендуется client_first_name = ‘John’ client_last_name = ‘Doe’ # Также обратите внимание на следующий пример: # Не рекомендуется def fetch_clients(response, variable): # do something pass def fetch_posts(res, var): # do something pass # Рекомендуется def fetch_clients(response, variable): # do something pass def fetch_posts(response, variable): # do something pass
Начните отслеживать проблемы (issues) в кодовой базе в своем редакторе.
Для содержания кодовой базы в чистоте очень важно сделать так, чтобы другим разработчикам было легко видеть и отслеживать проблемы в коде. Когда вы можете это делать прямо в своем редакторе, вы:
- получаете полное представление о техническом долге
- видите контекст каждой проблемы
- избавляетесь от лишнего переключения контекстов
- можете работать с техническим долгом непрерывно.
Конечно, вы можете использовать различные инструменты для отслеживания технического долга, но лучше начать пользоваться соответствующими расширениями для редактора кода. Самые популярные из них также интегрируются с Jira, Linear, Asana и другими инструментами для управления проектами.
Не используйте магические числа. Это жестко прописанные числа, которые встречаются в коде без всяких объяснений. Обычно они появляются в виде литералов, причем неоднократно.
import random # Не рекомендуется def roll_dice(): return random.randint(0, 4) # what is 4 supposed to represent? # Рекомендуется DICE_SIDES = 4 def roll_dice(): return random.randint(0, DICE_SIDES)
Функции
При именовании функций строго придерживайтесь соглашения об именах. Использование разных подходов будет путать читателя.
# Не рекомендуется def get_users(): # do something Pass def fetch_user(id): # do something Pass def get_posts(): # do something Pass def fetch_post(id): # do something pass # Рекомендуется def fetch_users(): # do something Pass def fetch_user(id): # do something Pass def fetch_posts(): # do something Pass def fetch_post(id): # do something pass
Каждая функция должна выполнять какое-то одно действие и делать это хорошо. Пишите короткие и простые функции, выполняющие одну задачу. Полезный прием: если в имени вашей функции появляется союз «и», лучше разделить такую функцию на две разных.
# Не рекомендуется def fetch_and_display_users(): users = [] # result from some api call for user in users: print(user) # Рекомендуется def fetch_usersl(): users = [] # result from some api call return users def display_users(users): for user in users: print(user)
Не используйте Boolean flags. Это переменные, содержащие булевы значения — True или False. Они передаются в функцию для определения ее поведения.
text = "Python is a simple and elegant programming language." # Не рекомендуется def transform_text(text, uppercase): if uppercase: return text.upper() else: return text.lower() uppercase_text = transform_text(text, True) lowercase_text = transform_text(text, False) # Рекомендуется def transform_to_uppercase(text): return text.upper() def transform_to_lowercase(text): return text.lower() uppercase_text = transform_to_uppercase(text) lowercase_text = transform_to_lowercase(text)
Классы
Не добавляйте лишний контекст. Например, не следует добавлять ненужные слова к именам переменных.
# Не рекомендуется class Person: def __init__(self, person_username, person_email, person_phone, person_address): self.person_username = person_username self.person_email = person_email self.person_phone = person_phone self.person_address = person_address # Рекомендуется class Person: def __init__(self, username, email, phone, address): self.username = username self.email = email self.phone = phone self.address = address
В этом примере мы находимся внутри класса Person, поэтому нет нужды добавлять префикс person_ к каждой переменной класса.
Бонус: модульность кода
Чтобы ваш код оставался организованным и поддерживаемым, распределяйте логику по разным файлам или классам — т. н. модулям. В Python модуль — это просто файл, имеющий расширение .py. Каждый модуль должен фокусироваться на какой-то одной задаче.
От редакции Pythonist. О модулях можно почитать в статье «Как импортировать в Python?».
Вы можете придерживаться принципов объектно-ориентированного программирования, таких как инкапсуляция, абстракция, наследование и полиморфизм.
Заключение
Чистый код дает много преимуществ. Здесь и улучшение качества ПО, и легкая поддержка, и уменьшение технического долга.
В этой статье мы рассмотрели само понятие чистого кода и несколько советов о том, как писать чистый код на Python. Учтите, что это переходные знания: они вам пригодятся и при работе с любым другим языком программирования.
Как создать красивый GUI на Python?
Возможно это уже избитый вопрос — как создать GUI на Python. И всё-таки. Я бы не хотел использовать PyQt и PySide (не устраивают условия лицензии), а Kivy не очень нравится. Есть ли ещё библиотеки для Python GUI? Я собираюсь создать приложение для Android. Мне лично нравится TKinter. Можно ли в TKinter указать стили элементов (кнопок, надписей и т.п.)? Или существует способ использовать Figma для Python? Существует ли альтернатива Qt Designer для Python? Я буду очень благодарен за полезный ответ!
Отслеживать
задан 30 окт 2021 в 11:34
user467993 user467993
По поводу Figma, можно посмотреть Tkinter-Designer
7 апр 2022 в 5:39
Связанный вопрос: Визуальный редактор графического интерфейса для tkinter
7 апр 2022 в 5:40
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Если вам не сильно нравится, kivy есть kivymd, в данном фреймворке все виджеты стилизованы. Также скоро выйдет программа kivymd builder. Он будет работать как qtdesigner. Вот ссылка на гитхаб проекта:
Также сам фреймворк активно поддерживается. Каждую неделю выходят множество обновлений.
Ну, если всё-таки вы не изменили своё, мненение о kivy и kivymd. То я нашёл ещё одну, это eel, хотя я честно скажу, мне eel полностью не нравится, он не поддерживает, многооконность и в нём слабо реализована асинхронность.
Идеальный код на Python
Главная ошибка новичка: он пишет код и не думает о том, что его будет кто-то читать. Более того, он не берет в расчет, что сам будет вникать в эти строки спустя день, неделю или год. Новичок решает другую задачу: пишет код, который будет работать.
Проблема в том, что если работодатель видит код, но не может сразу его прочитать, остальное уже не важно. Сотрудник с таким стилем кодинга будет создавать проблемы для коллег — значит, компании он не нужен.
У нас уже вышла публикация о том, как написать код для собеседования и получить работу. Мы пошли дальше и задали вопросы об идеальном коде декану Python-факультета GeekUniversity Алексею Петренко. Он рассказал, что в коде выдает джуниора.

Отступы: все разные
В современных языках программирования существует правило: для выделения самостоятельных смысловых логических блоков используют отступы от начала строки. Python ушел дальше всех: отступ является непосредственным атрибутом этого языка программирования, это часть синтаксиса.
Что новички делают не так
- Неправильно выставляют отступы — их код просто не работает.
- Используют неодинаковое количество отступов: в одной функции — два пробела, в другой — все шесть.
- Используют разные клавиши, чтобы создать отступ: в одной функции — клавишу табуляции, в другой — два пробела.
Из-за разных отступов код смотрится некрасиво, а Python ругает за неудачное сочетание пробелов и табуляций.
Решение
Хороший тон — делать отступ четырьмя нажатиями пробела.
Современные среды разработки — например, PyCharm — упрощают жизнь программиста. Нажав клавишу табуляции, автоматически получаете четыре пробела. Вуаля: код оформлен в общепризнанном стиле.

Для языка Python разработан официальный документ PEP-8, в котором прописаны правила красивого кода. Это соглашение всех программистов мира, которые пишут на Python, о том, какой код считать образцовым.
Переменные: непонятные
Рабочий код должен быть читаемым и ясным без личного присутствия автора. Потрудитесь дать понятные имена всем переменным, методам, функциям, которые используете в коде.
Что новички делают не так
- Используют в качестве переменных обычные буквы алфавита: a, b, c, d, — не задумываясь о смысловой нагрузке.
- Называют все переменные любимой буквой, добавляя цифры: а1, а2, а3. Если переменных двадцать, то будет и а20. Понять, какую информацию они хранят, очень сложно.
- Используют строчную переменную l. Разработчики стараются избегать эту букву. Ее не принято использовать не только в Python, но и в других языках программирования, потому что при быстром чтении кода строчную l легко спутать с единицей. Аналогичная путаница возникает с O и 0.
- Записывают переменные транслитом (massiv вместо array).
- Придумывают новые переменные для общепринятых: для названия цикла (в цикле используют переменные i, j, k — именно в таком порядке, от внешнего i до вложенного k), для обозначения осей координат (x, y).
Решение
Очередное правило хорошего кода: каждая переменная должна говорить о том, что она хранит. Для записи информации о человеке логично создать переменную name. Для возраста — age. Заглядывайте в онлайн-словари, чтобы называть переменные правильными английскими словами, понятными большинству программистов в мире. Идеальная переменная понятна и легко читается:
- Если название переменной состоит из нескольких слов, используйте в Python нижнее подчеркивание: переменная со значением максимального размера — max_size.
- Если именуете класс, записывайте каждое слово с заглавной буквы: имя_переменной должно отличаться от ИмениКласса.
Особенность языка Python в том, что он интерпретируемый. Программа не отслеживает, какие имена дает программист переменным, и примет любое имя, даже название функции.
Из этого вытекает еще одна ошибка новичков: они называют переменные так же, как функции.
В Python есть около 70 функций «из коробки»: функция sum() вычисляет сумму всех переданных аргументов, max() ищет максимальное значение. Если программист назовет переменную sum, она будет работать. Но такой переменной он переопределит функцию суммирования — и она сломается.

Пустые строки: отсутствуют или в избытке
Как правило, код джуниора идет сплошным текстом: в каждой строке — очередная строка кода.
Что новички делают не так
- Не разделяют строки кода пустыми строками.
- Отделяют каждую строчку кода пустой строкой.
В обоих случаях код очень сложно прочитать.
Решение
Код принято делить на логические блоки.
К примеру, если запрашивают информацию о пользователе, пишут несколько строк кода и оставляют одну пустую после блока.
Далее идет блок обработки информации. Если он содержит несколько подблоков, их тоже следует отделить пустой строкой.
Перед выводом информации в конце также добавляют пустую строку.

Слишком сжатый код
Что новички делают не так
- Пытаются написать код максимально сжато и для этого помещают несколько составных операций в одну строку.
Такой код сложно отлаживать в больших проектах: его трудно читать, приходится разбираться в том, как он работает.
Решение
Если есть возможность, распишите несколько составных действий в отдельные строки. Лучше потратить две минуты сейчас и сэкономить двадцать минут на чтение этого кода в будущем.
Советы декана начинающим разработчикам
- Ваш код будут читать другие программисты. Всегда думайте о том, как они его воспримут, насколько он будет понятен коллегам.
- Потратьте время на изучение синтаксиса, почитайте стандарты PEP8. Есть англоязычная версия и перевод. Работодатель будет встречать «по одежке»: ваш код должен выглядеть красиво.
- Если Python — не первый для вас язык программирования, повторяйте требования стиля. Когда разработчик пишет, не соблюдая их, возникает путаница: то ли перед нами человек, у которого в голове перемешались все языки программирования, то ли новичок, который вообще ничего не знает о Python.
- Воспользуйтесь командой import this. Это пасхалка от разработчиков: она выводит свод правил хорошего кода. Почаще перечитывайте этот Дзен Python — и ваш код будет идеален.
Придерживаясь этих советов, вы быстро научитесь писать код, который устроит вас, коллег и работодателя.
Улучшение Python-кода: 12 советов для начинающих
В мои обязанности входит наём Python-разработчиков. Если у заинтересовавшего меня специалиста есть GitHub-аккаунт — я туда загляну. Все так делают. Может быть, вы этого и не знаете, но ваш домашний проект, не набравший ни одной GitHub-звезды, может помочь вам в получении работы.
То же самое относится и к тестовым задачам, выдаваемым кандидатам на должность программиста. Как известно, мы, когда впервые видим человека, формируем первое впечатление о нём за 30 секунд. Это влияет на то, как мы будем, в дальнейшем, оценивать этого человека. Мне кажется несправедливым то, что люди, обладающие привлекательной внешностью, добиваются всего легче, чем все остальные. То же самое применимо и к коду. Некто смотрит на чей-то проект и что-то тут же бросается ему в глаза. Ошмётки старого кода в репозитории — это как крошки хлеба, застрявшие в бороде после завтрака. Они могут напрочь испортить первое впечатление. Может, бороды у вас и нет, но, думаю, вам и так всё ясно.

Обычно легко понять то, что некий код написан новичком. В этом материале я дам вам несколько советов о том, как обыграть кадровиков вроде меня и повысить свои шансы на получение приглашения на собеседование. При этом вас не должна мучить мысль о том, что, применяя эти советы, вы кого-то обманываете. Вы не делаете ничего дурного. Применяя те небольшие улучшения кода, о которых пойдёт речь, вы не только повышаете свои шансы на успешное прохождение собеседования, но и растёте как программист. Не могу сказать, что профессиональному росту способствует упор на заучивание алгоритмов или модулей стандартной библиотеки.
В чём разница между новичком и более опытным разработчиком? Новичок не работал с устаревшими кодовыми базами. Поэтому он не видит ценности в том, чтобы вкладывать время в написание кода, который легко поддерживать. Часто новички работают в одиночку. Они, в результате, не особенно заботятся о читабельности кода.
Ваша цель заключается в том, чтобы показать то, что вас заботит читабельность вашего кода и возможность его поддержки в будущем.
Поговорим о том, как повысить качество ваших Python-проектов. Советы, которыми я хочу поделиться, улучшат ваш код. А если вы не сделаете из них карго-культ, то они ещё и помогут вашему профессиональному росту.
1. Уберите из репозитория ненужные файлы
Откройте страницу своего репозитория на GitHub. Есть ли в нём файлы с расширениями .idea , .vscode , .DS_Store или .pyc ? Попали ли туда файлы из виртуального окружения? Если так — избавьтесь от всего этого и добавьте записи о соответствующих файлах и папках в .gitignore . Выкладывая код на GitHub следует придерживаться правила, в соответствии с которым в репозиторий не должно попадать ничего такого, что создано не владельцем репозитория. Вот хорошее руководство по .gitignore , в котором даётся обзор того, что обычно не стоит включать в репозитории.
▍Примеры
Начальный вариант файла .gitignore для Python-проектов
Следующий текст можно рассматривать в качестве начального варианта содержимого .gitignore . Добавьте такой файл в свой проект в самом начале работы над ним.
*.pyc *.egg-info # Если вы программируете на Mac .DS_Store # Если вы пользуетесь виртуальными окружениями # в проектах. Я, например, обычно ими пользуюсь. /env # Настройки и хранение секретных данных (подробнее об этом - в следующем разделе) /.env
Если вам нужен более масштабный пример .gitignore — взгляните на этот файл из коллекции GitHub. Используйте его как источник вдохновения и как базу для вашего .gitignore .
2. Не храните в коде секретные данные
В репозитории не должно быть никаких паролей к базам данных, ключей к внешним API, секретных ключей систем шифрования! Подобные вещи надо хранить в конфигурационных файлах или в переменных окружения. Ещё один вариант — их чтение из защищённого хранилища. А включать их в код — это в высшей степени неправильно. Вот — отличное руководство на тему хранения конфигурационных данных, подготовленное в рамках проекта The Twelve-Factor App (другие материалы этого проекта тоже весьма полезны).
▍Примеры
Неправильно: реквизиты базы данных хранятся в коде
Ниже приведён фрагмент Flask-приложения. Автор хранит реквизиты для доступа к базе данных в коде.
from flask import Flask app = Flask(__name__) app.config["SQLALCHEMY_DATABASE_URI"] = "postgresql://user:secret@localhost:5432/my_db"
Правильно: реквизиты хранятся в переменных окружения
Перенести реквизиты для доступа к базе данных в переменные окружения совсем несложно:
import os from flask import Flask app = Flask(__name__) app.config["SQLALCHEMY_DATABASE_URI"] = os.getenv("SQLALCHEMY_DATABASE_URI")
Теперь нужно, перед запуском приложения, инициализировать переменные окружения:
export SQLALCHEMY_DATABASE_URI=postgresql://user:secret@localhost:5432/my_db flask run
Правильно: реквизиты хранятся в файле .env
Для того чтобы перед запуском программы не приходилось бы вручную инициализировать переменные окружения, можно пойти дальше. А именно, речь идёт о том, чтобы сохранить эти данные в файле .env . Далее, нужно установить пакет python-dotenv и инициализировать переменные окружения прямо из Python-кода.
Вот как может выглядеть файл .env :
SQLALCHEMY_DATABASE_URI=postgresql://user:secret@localhost:5432/my_db
Вот как работать с этим файлом из кода:
import os from dotenv import load_dotenv from flask import Flask load_dotenv() app = Flask(__name__) app.config["SQLALCHEMY_DATABASE_URI"] = os.getenv("SQLALCHEMY_DATABASE_URI")
И надо не забыть добавить запись об .env в .gitignore . Благодаря этому данный файл не будет случайно выгружен в репозиторий.
3. Добавьте в репозиторий файл README
В проекте, на его верхнем уровне, должен присутствовать файл README , в котором описана цель создания проекта, в котором даются инструкции по установке проекта и по началу работы с ним. Если вы не знаете о том, что писать в таком файле, обратитесь к руководству, размещённому на сайте Make a README.
▍Примеры
Файл README для Python-проекта
Тут приведён пример файла README , созданный в соответствии с рекомендациями вышеупомянутого сайта. Так, здесь есть сведения о проекте, руководство по его установке и использованию. Здесь же присутствует раздел, предназначенный для тех, кто хочет внести вклад в работу над проектом. В файле есть и сведения о лицензии, что очень важно для опенсорсных проектов.
# Foobar Foobar is a Python application for dealing with word pluralization. ## Installation Clone the repository from GitHub. Then create a virtual environment, and install all the dependencies. ```bash git clone https://github.com/username/foobar.git python3 -m venv env source env/bin/activate python -m pip install -r requirements.txt ``` ## Usage Initialize the virtual environment, and run the script ```bash source env/bin/activate ./pluralize word words ./pluralize goos geese ``` ## Contributing Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. Please make sure to update the tests as appropriate. ## License [MIT](https://choosealicense.com/licenses/mit/)
4. Если вы используете сторонние библиотеки — добавьте в репозиторий файл requirements.txt
Если в проекте используются сторонние зависимости, об этом нужно сообщить. Легче всего это сделать, создав файл requirements.txt в корневой директории проекта. В каждой строке этого файла приводятся сведения об одной зависимости. Нужно, кроме того, добавить инструкции по работе с этим файлом в README . Подробности о requirements.txt можно найти в руководстве пользователя по pip .
▍Примеры
Файл requirements.txt для Flask-приложения
Добавление файла requirements.txt в корневую директорию проекта — это самый лёгкий способ отслеживания зависимостей. Можно, помимо сведений о самих зависимостях, дать сведения и об их версиях. Вот пример файла requirements.txt :
gunicorn Flask>=1.1 Flask-SQLAlchemy psycopg2
Указание более подробных сведений о зависимостях с использованием файла requirements.in
При работе над любым проектом всегда полезно иметь возможность воспроизведения его окружения. В результате, даже если вышла новая версия какой-нибудь библиотеки, можно использовать старую, проверенную в деле версию, работая с ней до тех пор, пока не будет решено перейти на новую. Это называется «фиксацией зависимостей». Легче всего это можно сделать, прибегнув к pip-tools. При таком подходе в вашем распоряжении окажется два файла: requirements.in и requirements.txt . Второй из них при этом вручную не модифицируют, просто добавляя его в репозиторий вместе с requirements.in . Вот как выглядит файл requirements.in :
gunicorn Flask>=1.1 Flask-SQLAlchemy psycopg2
Для того чтобы на основе этого файла был бы автоматически создан requirements.txt , файл requirements.in компилируют, используя команду pip-compile . Вот как выглядит автоматически сгенерированный файл requirements.txt :
# # This file is autogenerated by pip-compile # To update, run: # # pip-compile # click==7.1.2 # via flask flask-sqlalchemy==2.4.4 # via -r requirements.in flask==1.1.2 # via -r requirements.in, flask-sqlalchemy gunicorn==20.0.4 # via -r requirements.in itsdangerous==1.1.0 # via flask jinja2==2.11.2 # via flask markupsafe==1.1.1 # via jinja2 psycopg2==2.8.6 # via -r requirements.in sqlalchemy==1.3.19 # via flask-sqlalchemy werkzeug==1.0.1 # via flask # The following packages are considered to be unsafe in a requirements file: # setuptools
Как видите, готовый файл содержит сведения о точных версиях всех зависимостей.
5. Форматируйте код с помощью black
Неоднородное форматирование кода не помешает ему нормально работать. Но если код хорошо отформатирован — это улучшит его читабельность и упростит его поддержку. Форматирование кода может и должно быть автоматизировано. Если вы пользуетесь VS Code, то можете увидеть рекомендацию по установке black в качестве автоматического средства форматирования исходного кода, написанного на Python. Форматирование кода производится при сохранении файлов. Кроме того, black можно установить самостоятельно и форматировать код, пользуясь средствами командной строки.
▍Примеры
Неправильно: неформатированный код
Код, приведённый ниже, тяжело читать и расширять.
def pluralize ( word ): exceptions= < "goose":'geese','phenomena' : 'phenomenon' >if word in exceptions : return exceptions [ word ] return word+'s' if __name__=='__main__' : import sys print ( pluralize ( sys.argv[1] ) )
Правильно: тот же самый код, отформатированный с помощью black
Применение black гарантирует то, что переформатированный код будет работать так же, как его исходный вариант. Данный инструмент всего лишь снимает с программиста нагрузку по ручному форматированию кода.
def pluralize(word): exceptions = if word in exceptions: return exceptions[word] return word + "s" if __name__ == "__main__": import sys print(pluralize(sys.argv[1]))
6. Избавьтесь от ненужных команд импорта
Ненужные команды импорта обычно остаются в коде после каких-нибудь экспериментов и после рефакторинга. Если в программе не используется некий модуль, который раньше в ней применялся, не забудьте убрать из кода соответствующую команду импорта. Обычно редакторы подсвечивают неиспользуемые команды импорта, что облегчает их поиск и борьбу с ними.
▍Примеры
Неправильно: наличие в коде ненужных команд импорта
В этом фрагменте кода импортированный модуль os не используется:
import os print("Hello world")
Правильно: в коде нет ненужных команд импорта
Вышеприведённый код очень просто привести в приличный вид:
print("Hello world")
7. Избавьтесь от ненужных переменных
То, о чём говорилось в предыдущем пункте, относится и к неиспользуемым переменным. Они могут попасть в код в те моменты, когда программист создаёт их, думая, что они могут пригодиться в дальнейшем, а потом оказывается, что они не нужны.
▍Примеры
Неправильно: наличие в коде ненужной переменной:
Здесь переменная response не используется:
def ping(word): response = requests.get("https://example.com/ping")
Правильно: в коде нет ненужных переменных
Тут нет ничего лишнего:
def ping(word): requests.get("https://example.com/ping")
8. Следуйте соглашению по именованию сущностей из PEP 8
Именование сущностей — это как форматирование. Неудачный выбор имён не помешает правильной работе программы, но затруднит работу с кодом. Кроме того, единообразный подход к именованию сущностей снимает с программиста нагрузку, связанную с постоянным выдумыванием имён. Почитать PEP 8 можно здесь.
▍Примеры
Правила именования сущностей из PEP 8
- Имена файлов и директорий записываются в нижнем регистре с использованием символа подчёркивания для разделения слов: lowercase_underscores .
- Так же составляют имена функций и переменных: lowercase_underscores .
- Имена классов записывают с использованием «верблюжьего» стиля: CamelCase .
- Имена констант записываются в верхнем регистре с использованием символа подчёркивания: UPPERCASE_UNDERSCORE .
Пример применения PEP 8
Ниже приведён фрагмент кода, имеющего достаточно сложную структуру, но соответствующего правилам PEP 8. Тут я, чтобы продемонстрировать именование разных сущностей, поместил простую функцию в класс.
#!/usr/bin/env python import sys DEFAULT_NAME = "someone" # ") if __name__ == "__main__": GreetingManager().say_hello(sys.argv)
9. Проверяйте код с использованием линтера
Линтер анализирует код и ищет в нём ошибки, которые можно обнаружить автоматически. Перед отправкой изменений в репозиторий код всегда полезно проверять с помощью линтера.
Различные IDE и редакторы кода, вроде pycharm и VS Code, содержат встроенные линтеры и подсвечивают проблемные участки кода. Программист сам принимает решение о том, следовать этим рекомендациям или нет. Поначалу сообщения об ошибках, выдаваемые линтерами, могут показаться непонятными. Для того чтобы в них ориентироваться, стоит уделить некоторое время изучению используемого линтера. Это себя окупит.
Если говорить о линтерах, представленных инструментами командной строки, то в этой сфере я порекомендовал бы flake8. Этот линтер обладает разумными настройками, применяемыми по умолчанию. Обычно ошибки, о которых он сообщает, стоит исправлять. Если вы хотите строже относиться к своему коду — взгляните на pylint. Этот линтер способен выявлять множество ошибок, в число которых входят и те, о которых мы тут не говорим.
▍Примеры
Файл, который нужно почистить
В нижеприведённом коде (файл ping.py ) можно увидеть некоторые проблемы и без применения линтера.
import requests import os def PingExample(): result = requests.get("https://example.com/ping")
Давайте проанализируем его с помощью flake8 и pylint .
Результаты анализа кода с помощью flake8
flake8 ping.py ping.py:2:1: F401 'os' imported but unused ping.py:4:1: E302 expected 2 blank lines, found 1 ping.py:5:5: F841 local variable 'result' is assigned to but never used
Результаты анализа кода с помощью pylint
pylint ping.py ************* Module ping ping.py:1:0: C0114: Missing module docstring (missing-module-docstring) ping.py:4:0: C0103: Function name "PingExample" doesn't conform to snake_case naming style (invalid-name) ping.py:4:0: C0116: Missing function or method docstring (missing-function-docstring) ping.py:5:4: W0612: Unused variable 'result' (unused-variable) ping.py:2:0: W0611: Unused import os (unused-import) ping.py:2:0: C0411: standard import "import os" should be placed before "import requests" (wrong-import-order) -------------------------------------------------------------------- Your code has been rated at -5.00/10 (previous run: -5.00/10, +0.00)
10. Удалите из кода команды print, используемые при отладке
Отладка кода с использованием команд print , расположенных в его важнейших местах, — это нормально. Но не стоит, решив проблему, коммитить в репозиторий код, содержащий подобные команды.
▍Примеры
Неправильно: отладочные команды print в коде
Автор кода захотел узнать о том, к каким изменениям в файловой системе приведёт работа функции, сохраняющей объект в файл. Команды print , выполняемые до и после вызова тела функции, не решают никаких задач, имеющих отношение к самой функции. После того, как они помогли программисту разобраться в происходящем, их нужно удалить. Иначе они будут просто засорять код.
def serialize(obj, filename): print("BEFORE", os.listdir()) with open(filename, "wt") as fd: json.dump(obj, fd) print("AFTER", os.listdir())
Правильно: код без ненужных команд print
Если убрать из кода отладочные команды — это уменьшит размер функции и повысит удобство работы с ней. А это всегда хорошо.
def serialize(obj, filename): with open(filename, "wt") as fd: json.dump(obj, fd)
11. Не держите в репозитории закомментированный код
Очищайте репозиторий от закомментированных старых версий кода и от закомментированного кода, который был написан для проведения каких-нибудь экспериментов. Если вы когда-нибудь решите вернуться к старой версии программы — это всегда можно сделать с помощью инструментов применяемой вами системы контроля версий. Остатки старого кода сбивают с толку тех, кто читает тексты программ. Такой код создаёт впечатление небрежного отношения к нему его автора.
▍Примеры
Неправильно: ненужные комментарии в коде
Автор экспериментировал, прямо в коде программы, с преобразованием строк. Решено было не включать результаты этих экспериментов в итоговый вариант программы, но, на всякий случай, соответствующий код не удалили полностью, а лишь закомментировали.
name = input("What's your name: ") #short_name = name.split()[0] #if len(short_name) > 0: # name = short_name print(f"Hello, ")
Правильно: код, в котором нет ненужных комментариев
Обратите внимание на то, насколько легче читать предыдущий код, из которого убраны ненужные комментарии.
name = input("What's your name: ") print(f"Hello, ")
12. Оформляйте скрипты в виде функций
В самом начале работы над программой её код обычно следует за потоком мыслей программиста. Этот код состоит из последовательности инструкций, решающих некую задачу. Выработайте у себя привычку оформлять последовательности инструкций в виде функций. Поступать так стоит с самого начала работы над проектом. Подобные функции нужно вызывать в самом конце программ, защитившись выражением if __name__ == «__main__» . Это поможет вам использовать структурный подход при развитии проекта, извлекая из нужных мест вспомогательные функции. А позже, если надо, это облегчит оформление скриптов в виде модулей.
▍Примеры
Неправильно: скрипт, не оформленный в виде функции
Выполнение кода в этом примере начинается в первой строке и заканчивается в последней. Такой подход оправдан в том случае, если речь идёт о простых скриптах. Но если код скрипта окажется сложнее, воспринять его будет уже не так легко.
#!/usr/bin/env python name = input("What's your name: ") print(f"Hello, ")
Правильно: скрипт, оформленный в виде функции
Поток выполнения программы начинается в последней строке кода — там, где вызывается функция say_hello() . Если речь идёт о том, что в состав функции входит всего пара строк кода, то такой подход может показаться неоправданно усложнённым. Но это, в любом случае, облегчает изменение кода. Например, можно легко, воспользовавшись click, оснастить свою функцию возможностями по приёму параметров из командной строки.
#!/usr/bin/env python def say_hello(): name = input("What's your name: ") print(f"Hello, ") if __name__ == "__main__": say_hello()
Домашнее задание
Говорят, что мы запоминаем лишь 10% того, что прочли. Это значит, что вы запомните лишь один из 12 данных мной советов. Полагаю, это означает, что вы впустую потратили время, читая эту статью. А я, в таком случае, зря её писал.
Но, к счастью, есть одна хитрость. Известно, что практика позволяет сохранить около 80% знаний. Следовательно — вот вам задание: возьмите один из своих проектов и проанализируйте его с точки зрения моих 12 советов. У того, кто так и сделает, в 8 раз больше шансов профессионально вырасти, чем у того, кто просто прочтёт статью.
Есть ли в ваших Python-проектах недочёты, о которых говорит автор этой статьи?
