Какую команду нужно запустить чтобы отформатировать этот файл в соответствии с рекомендациями pep8
Python, точнее его самый известный представитель CPython, не очень предназначен для каких-либо быстрых расчетов. Иначе говоря, производительность у него не такая уж хорошая. А вот скорость разработки и читаемости отличная.
О читаемости и пойдет речь, а точнее как ее увеличить.
Зачем нужен PEP 8
“Читаемость имеет значение”, — Дзен Python
PEP 8 существует для улучшения читаемости кода Python. Но почему так важна удобочитаемость? Почему написание читаемого кода является одним из руководящих принципов языка Python?
Как сказал Гвидо ван Россум: «Код читают гораздо чаще, чем пишут». Вы можете потратить несколько минут или целый день на написание фрагмента кода для аутентификации пользователя. В дальнейшем вам не придётся его писать. Но перечитывать его вы точно будете. Этот фрагмент кода может остаться частью проекта, над которым вы работаете. Каждый раз, возвращаясь к этому файлу, вам нужно будет вспомнить, что делает этот код и зачем вы его написали. Поэтому удобочитаемость имеет большое значение.
Если вы новичок в Python, возможно, вам уже через несколько дней или недель будет трудно вспомнить, что делает фрагмент кода. Но если вы следуете PEP 8, вы можете быть уверены, что правильно назвали свои переменные . Вы будете знать, что добавили достаточно пробелов, чтобы обособить логические шаги. Вы также снабдили свой код отличными комментариями. Все это сделает ваш код будет более читабельным, а значит, к нему будет легче вернуться. Следование правилам PEP 8 для новичка может сделать изучение Python гораздо более приятной задачей.
Следование PEP 8 особенно важно, если вы претендуете на должность разработчика. Написание понятного, читаемого кода свидетельствует о профессионализме. Это скажет работодателю, что вы понимаете, как правильно структурировать свой код.
Работая над проектами, вам, скорее всего, придется сотрудничать с другими программистами. Здесь, опять же, очень важно писать читаемый код. Другие люди, которые, возможно, никогда раньше не встречали вас и не видели ваш стиль программирования, должны будут прочитать и понять ваш код. Наличие руководящих принципов, которым вы следуете и которые знаете, облегчит другим чтение вашего кода.
Используйте is not, а не not … is в операторах if
Если вы пытаетесь проверить, имеет ли переменная какое-нибудь значение, есть два варианта. Первый – использовать оператор if с x is not None , как в примере ниже:
Второй вариант — оценить x is None , а затем применить оператор if , исходя из результата оператора not :
Хотя оба варианта выполнятся правильно, первый проще, поэтому PEP 8 рекомендует его.
Отступы
«Должен быть один – и желательно только один – очевидный способ сделать что-либо», — Дзен Python.
Отступы чрезвычайно важны в Python. Уровень отступа строк кода в Python определяет, как группируются операторы.
Рассмотрим следующий пример:
Оператор print с отступом сообщает Python, что он должен выполняться только в том случае, если if возвращает True. Тот же отступ применяется для указания Python, какой код выполнять при вызове функции или какой код принадлежит данному классу.
Ключевые правила отступов, изложенные в PEP 8, следующие:
- Используйте 4 последовательных пробела для обозначения отступа.
- Предпочитайте пробелы табуляции.
Используйте встроенные функции, такие как min(), max() и sum()
Ещё одна типичная задача программирования — это поиск минимального или максимального значения в массиве чисел. Найти наименьшее число в списке можно с помощью for:
Но более «питонически» применять встроенную функцию min():
То же касается нахождения наибольшего значения в списке: вместо цикла применяется встроенная функция max():
Чтобы найти сумму чисел списка, написать цикл for можно, но более питонически воспользоваться sum():
Также sum() полезна при подсчёте количества элементов списка, для которых выполняется некое условие. Например, вот цикл for для подсчёта числа начинающихся с буквы A строк списка:
Функция sum() со списковым включением сокращает цикл for до одной строки:
Красота! Но ещё более питонической эту строку сделает замена спискового включения на выражение-генератор. Убираем скобки списка:
Как именно работает код? И списковое включение, и выражение-генератор возвращают итерируемый объект со значением True, если строка в списке capitals начинается с буквы A, и False — если это не так:
В Python True и False — это завуалированные целые числа. True равно 1, а False — 0:
Когда в sum() передаётся списковое включение или выражение-генератор, значения True и False считаются 1 и 0 соответственно. Всего два значения True и два False, поэтому сумма равна 2.
Использование sum() для подсчёта числа удовлетворяющих какому-то условию элементов списка подчёркивает важность понятия «питонический». Я нахожу такое применение sum() очень питонически. Ведь с sum() используется несколько особенностей этого языка и создаётся, на мой взгляд, лаконичный и удобный для восприятия код. Но, возможно, не каждый разработчик на Python со мной согласится.
Можно было бы возразить, что в этом примере нарушается один из принципов Zen of Python: «Явное лучше неявного». Ведь не очевидно, что True и False — целые числа и что sum() вообще должна работать со списком значений True и False. Чтобы освоить это применение sum(), нужно глубоко понимать встроенные типы Python.
Узнать больше о True и False как целых числах, а также о других неожиданных фактах о числах в Python можно из статьи 3 Things You Might Not Know About Numbers in Python («3 факта о числах в Python, которых вы могли не знать»).
Жёстких правил, когда называть и не называть код питоническим, нет. Всегда есть некая серая зона. Имея дело с примером кода, который может находиться в этой серой зоне, руководствуйтесь здравым смыслом. Для удобства восприятия всегда применяйте err и не бойтесь обращаться за помощью.
Не используйте if x: если вы имеете в виду if x not None:
Иногда у вас может быть функция с аргументами, которые по умолчанию равны None. При проверке, присвоено ли такому аргументу arg другое значение, часто допускают следующую ошибку:
Этот код проверяет истинность аргумента. Но на самом деле вы хотите проверить, что arg не равен None , поэтому было бы лучше использовать следующее:
Здесь ошибка состоит в том, что not None и истинность приравниваются. Но вы могли установить arg = [] . Как мы видели выше, пустые списки в Python считаются ложными. Таким образом, даже несмотря на то, что аргумент arg был назначен, условие не выполняется, и поэтому код в теле оператора if игнорируется.
Пробелы в выражениях и утверждениях
«Разреженное лучше плотного», — Дзен Python.
Пробелы могут быть очень полезны в выражениях и операторах при правильном использовании. Если пробелов недостаточно, могут возникнуть трудности при чтении кода: он сливается в сплошное полотно. Если пробелов слишком много, может быть сложно визуально объединить связанные между собой операторы.
Английский для программистов
Наш телеграм канал с тестами по английскому языку для программистов. Английский это часть карьеры программиста. Поэтому полезно заняться им уже сейчас
Проблемы форматирования
Идеального форматирования кода не существует. Для каждого языка стоит подстраиваться под общепринятые правила оформления кода. Да что говорить, если среди новичков С++ еще до сих пор войны по поводу ставить скобки на следующей строке или нет.
Для python'а основными проблемами форматирования является «C стиль». Не редко в рассматриваемый язык приходят из С-подобных языков, а для них свойственно писать с символами ")(;".
Символы не единственная проблема, есть еще и проблема избыточности написания конструкций. Питон, в отличие от Java, менее многословен и чтобы к этому привыкнуть у новичков уходит большое количество времени.
Это две основные проблемы, которые встречаются чаще всего.
Пустые строки
Вертикальные пробелы (т.е. пустые строки) могут значительно улучшить читаемость вашего кода. Код, который сливается в сплошной блок, сложно просматривать. Но слишком много пустых строк делают код очень разреженным, и читателю придется прокручивать его куда чаще, чем хотелось бы. Ниже приведены три основных правила использования вертикальных пробелов.
Окружайте функции и классы верхнего уровня двумя пустыми строками
Функции и классы верхнего уровня должны быть довольно самодостаточными и реализовывать отдельные части функциональности. Имеет смысл обособить их, добавив дополнительное пространство по вертикали, чтобы было ясно, что они разделены:
Разделяйте определения методов в классах одной пустой строкой
Внутри класса все функции связаны друг с другом. Рекомендуется оставлять между ними только одну строку:
Используйте пустые строки внутри функций, чтобы показать четкие шаги
Иногда сложная функция должна выполнить несколько шагов до оператора return . Чтобы помочь читателю понять логику внутри функции, бывает полезно оставлять пустую строку перед каждым новым шагом.
В приведенном ниже примере есть функция для вычисления дисперсии списка. Это двухэтапная задача, поэтому я обозначил каждый шаг, оставив между ними пустую строку. Перед оператором возврата также есть пустая строка. Это помогает читателю ясно увидеть, что возвращает функция:
Аккуратное использование вертикальных пробелов может значительно улучшить читаемость вашего кода. Оно помогает читателю с первого взгляда понять, как ваш код разбивается на разделы и как эти разделы соотносятся друг с другом.
Отдавайте предпочтение списковым включениям, а не простым циклам for
Обработка элементов массива и сохранение результатов в новом — типичная задача программирования. Допустим, нужно преобразовать список чисел в список их квадратов. Избегая циклов в стиле C, можно написать:
Но более питонически применить списковое включение:
Списковые включения понять сразу может быть трудно, но они покажутся знакомыми тем, кто помнит математическую форму записи множества.
Вот так я обычно пишу списковые включения:
Начинаю с создания литерала пустого списка:
[].
Первым в списковое включение помещаю то, что обычно идёт в метод .append()при создании списка с помощью цикла for:
[num ** 2].
И, наконец, помещаю в конец списка заголовок цикла for:
[num ** 2 for num in nums].
Списковое включение — важное понятие, которое нужно освоить для написания идиоматичного кода Python, но ими не стоит злоупотреблять. Это не единственный вид списковых включений в Python. Далее поговорим о выражениях-генераторах и словарных включениях, вы увидите пример, когда спискового включения имеет смысл избегать.
Пробелы вокруг двоичных операторов
Следующие бинарные операторы нужно окружать пробелами с обеих сторон:
- Операторы присваивания (=, + =, — = и т. д.);
- Сравнения (==,! =,>, =, <=) и (is, is not, in, not in);
- Логические операторы (and, not, or).
Замечание. Когда = используется для присвоения значения по умолчанию аргументу функции, не окружайте его пробелами.
Когда в инструкции содержится более одного оператора, добавление одного пробела до и после каждого оператора может привести к путанице. Вместо этого лучше добавлять пробелы только вокруг операторов с самым низким приоритетом, особенно при выполнении математических манипуляций. Вот пара примеров:
Вы также можете применить это к операторам if с несколькими условиями:
В приведенном выше примере оператор and имеет самый низкий приоритет. Поэтому будет более ясным следующее выражение if :
Вы можете выбрать наиболее понятный вариант, с оговоркой, что будете использовать одинаковое количество пробелов по обе стороны от оператора.
В срезах двоеточия действуют как бинарные операторы. Следовательно, применяются правила, изложенные в предыдущем разделе, и с каждой стороны должно быть одинаковое количество пробелов. Допустимы следующие варианты оформления срезов списка:
Таким образом, вы должны окружить большинство операторов пробелами. Однако у этого правила есть некоторые оговорки, например, в аргументах функций или когда используется сразу несколько операторов.
Используйте .startswith() и .endswith() вместо срезов
Если вы пытались проверить, было ли слово префиксом или суффиксом в слове cat, может показаться разумным использовать срезы списков. Однако срезы подвержены ошибкам, и вам придётся явно указать количество символов в префиксе или суффиксе. А кому-то, менее знакомому с данным синтаксисом, вообще будут непонятны ваши намерения:
Это не так удобно, как использование .startswith() :
Тот же принцип применяется, когда вы проверяете последние элементы. В приведенном ниже примере показано, как можно проверить, заканчивается ли строка на jpg:
Хотя результат правильный, обозначения немного неуклюжи и их трудно читать. Вместо этого можно использовать .endswith() , как в примере ниже:
Как и в случае с большинством рекомендаций по программированию, целью этих является удобочитаемость и простота. В Python существует множество различных способов выполнения одного и того же действия, поэтому рекомендации по выбору методов крайне полезны.
Автоматизируем форматирование
Если посмотреть сколько всяких правил в pep8, то можно сесть за рефакторинг надолго. Вот только это лениво, да и при написании нового кода сиравно будут какие-то ошибки правил. Для этого рассмотрим как же себе можно упростить жизнь.
Дабы иметь представление сколько ошибок оформления в коде, стоит использовать утилиту pep8.
У нее достаточный список параметров, который позволяет рекурсивно просмотреть все файлы в папках на предмет соответствия стандарту pep8.
Вывод утилиты примерно такой:
По нему можно однозначно понять: где ошибка и что случилось.
autopep8
Ошибки стандарта часто повторяются от файла в файлу. И возникает сильное желание исправление автоматизировать. В этом случае на арену выходит autopep8.
Как и pep8, он умеет самостоятельно определять ошибки, а также исправлять их. Список исправляемых ошибок форматирования можно найти здесь
Само использование autopep8 крайне простое и может выглядеть так:
После выполнения данной команды, утилита рекурсивно пойдет по подпапкам и начнет в самих же файлах исправлять ошибки.
autoflake
Можно пойти дальше и в качестве оружия взять autoflake. Эта утилита помогает удалить не используемые импорты и переменные.
Используется примерно так:
Тем самым будут рекурсивно почищены файлы в директории.
unify
Крайний, заключительный момент в редактировании кода — это строки. Кто-то любит их писать в одиночных апострофах, кто-то в двойных. Вот только и для этого существует рекомендации, а также и утилита, которая позволяет автоматически приводить в соответствие — unify
Использование:
Как и везде, утилита выполнит свое грязное дело рекурсивно для файлов в папке.
docformatter
Все время говорим о самом коде, а о комментариях еще ни разу не шло речи. Настало время — docformatter. Эта утилита помогает привести ваши docstring по соглашению PEP 257. Соглашение предписывает как следует оформлять документацию.
Использование утилиты ничуть не сложнее предыдущих:
А все вместе можно?
Выше описаны утилиты, их запуск можно добавить какой-нибудь bash скрипт под магическим названием clean.bash и запускать. А можно пойти и по другому пути и использовать wrapper над этими утилитами — pyformat
Не сравнивайте логические значения с True или False при помощи оператора эквивалентности (==)
Вам часто придется проверять, является ли логическое значение истинным или ложным. Кажется очевидным, что это стоит сделать при помощи оператора == :
Но на самом деле здесь нет необходимости в использовании оператора эквивалентности. bool может принимать только значения True или False . Поэтому достаточно написать следующее:
Этот способ выполнения оператора if с логическим значением требует меньше кода и выглядит проще, поэтому PEP 8 поощряет его.
Когда стоит игнорировать PEP 8
Краткий ответ на этот вопрос – никогда. Если вы строго следуете PEP 8, то можете гарантировать, что у вас будет чистый, профессиональный и читабельный код. Это принесет пользу вам, а также сотрудникам и потенциальным работодателям.
Однако некоторые рекомендации в PEP 8 неудобны в следующих случаях:
- соблюдение PEP 8 нарушает совместимость с существующим программным обеспечением
- код, связанный с тем, над чем вы работаете, несовместим с PEP 8
- код должен оставаться совместимым со старыми версиями Python
Строки документации
Строки документации (docstrings) — это строки, заключенные в три пары двойных ( """ ) или одинарных ( ''' ) кавычек. Они пишутся в первой строке любой функции, класса, метода или модуля. Вы можете использовать их для объяснения и документирования конкретного блока кода. Существует отдельный PEP — PEP 257, который охватывает эту тему, но вы получите краткое изложение в этом разделе.
Наиболее важные требования к строкам документации следующие:
- Окружайте строки документации тремя двойными кавычками с каждой стороны. Вот так: """Это строка документации""" .
- Пишите их для всех общедоступных ( public ) модулей, функций, классов и методов.
- Помещайте кавычки, завершающие ваш многострочный комментарий, на отдельной строке:
- Для однострочных комментариев оставляйте закрывающие кавычки """ в той же строке:
Более подробную информацию о документировании кода Python читайте в статье «Documenting Python Code: A Complete Guide» Джеймса Мертца.
От редакции Pythonist. Рекомендуем статью «Составление документации для проектов на Python».
Как проверить соответствие кода PEP 8
Чтобы убедиться, что ваш код соответствует PEP 8, необходимо многое проверить. Помнить все эти правила при разработке кода может быть непросто. Особенно много времени уходит на приведение прошлых проектов к стандарту PEP 8. К счастью, есть инструменты, которые помогут ускорить этот процесс.
Существует два класса инструментов, которые можно использовать для обеспечения соответствия PEP 8: линтеры и автоформаттеры.
Как выбирать имена
Выбор имен для ваших переменных, функций, классов и т. д. может быть сложной задачей. Хорошо подобранные имена сделают ваш код более читабельным. Лучший способ – использовать информативные имена, чтобы было понятно, что представляет собой объект.
При именовании переменных у вас может возникнуть соблазн выбрать простые однобуквенные имена в нижнем регистре, например, x . Но если вы не используете x в качестве аргумента математической функции, непонятно, что он собой представляет. Представьте, что вы сохраняете имя человека в виде строки и хотите использовать срез, чтобы отформатировать его по-другому. У вас может получиться что-то вроде этого:
Это будет работать, но вам придётся разбираться, что собой представляют x , y и z . Это также может сбивать с толку ваших коллег. Более правильный выбор имен будет примерно таким:
Точно так же, в попытках уменьшить количество букв в имени, может возникнуть соблазн использовать сокращения. В приведенном ниже примере я определяю функцию db() , которая принимает единственный аргумент x и удваивает его:
На первый взгляд это могло показаться разумным выбором. db() легко может быть сокращением от double . Но представьте, что вы вернетесь к этому коду через несколько дней. Возможно, вы забыли, чего пытались достичь с помощью этой функции, и из-за этого будет сложно угадать, как вы ее сократили.
Следующий пример намного яснее. Если вы вернетесь к этому коду через пару дней после его написания, вы все равно сможете прочитать и понять назначение этой функции.
Та же философия применяется ко всем другим типам данных и объектам в Python. Всегда старайтесь использовать как можно более краткие, но информативные имена.
Используйте операции над множествами
Множества — это настолько недооценённая структура данных Python, что даже разработчики среднего уровня склонны их игнорировать, упуская возможности. Пожалуй, самое известное применение множеств в Python — это удаление повторяющихся в списке значений:
Но множества этим не ограничиваются. Я часто применяю их для эффективной фильтрации значений итерируемого объекта. Работа множеств лучше всего видна, когда нужны уникальные значения.
Вот придуманный, но реалистичный пример. У владельца магазина есть CSV-файл клиентов с адресами их почты. Снова возьмём файл clients.csv. Есть также CSV-файл заказов за последний месяц orders.csv, тоже с адресами почты:
Код нормальный и выглядит вполне питонически. Но что, если каждый месяц клиентов и заказов будут миллионы? Тогда при фильтрации почты и определении, каким клиентам отправлять купоны, потребуется перебор всего списка client_emails. А если в файлах client.csv и orders.csv есть повторяющиеся строки? Бывает и такое.
Более питонически считать адреса почты клиентов и заказов в множествах и отфильтровать множества почтовых адресов клиентов оператором разности множеств:
Этот подход намного эффективнее предыдущего: адреса клиентов перебираются только один раз, а не два. Вот ещё одно преимущество: все повторы почтовых адресов из обоих CSV-файлов удаляются естественным образом.
Три книги, чтобы писать более питонический код
За один день писать чистый питонический код не научиться. Нужно изучить много примеров кода, пробовать писать собственный код и консультироваться с другими разработчиками Python. Чтобы облегчить вам задачу, я составил список из трёх книг, очень полезных для понимания питонического кода. Все они написаны для программистов уровня выше среднего или среднего.
Если вы новичок в Python (и тем более в программировании в целом), загляните в мою книгу Python Basics: A Practical Introduction to Python 3 («Основы Python: Практическое введение в Python 3»).
Python Tricks Дэна Бейдера
Короткая и приятная книга Дэна Бейдера Python Tricks: A Buffet of Awesome Python Features («Приёмы Python: набор потрясающих функций Python») — отличная отправная точка для начинающих и программистов, желающих больше узнать о том, как писать питонический код.
С Python Tricks вы изучите шаблоны написания чистого идиоматичного кода Python, лучшие практики для написания функций, эффективное применение функционала объектно-ориентированного программирования Python и многое другое.
Effective Python Бретта Слаткина
Effective Python («Эффективный Python») Бретта Слаткина — это первая книга, которую я прочитал после изучения синтаксиса Python. Она открыла мне глаза на возможности питонического кода.
В Effective Python содержится 90 способов улучшения кода Python. Одна только первая глава Python Thinking («Мыслить на Python») — это кладезь хитростей и приёмов, которые будут полезными даже для новичков, хотя остальная часть книги может быть для них трудной.
Fluent Python Лучано Рамальо
Если бы у меня была только одна книга о Python, это была бы книга Лучано Рамальо Fluent Python («Python. К вершинам мастерства»). Рамальо недавно обновил свою книгу до современного Python. Сейчас можно оформить предзаказ. Настоятельно рекомендую сделать это: первое издание устарело.
Полная практических примеров, чётко изложенная книга Fluent Python — отличное руководство для всех, кто хочет научиться писать питонический код. Но имейте в виду, что Fluent Python не предназначена для новичков. В предисловии к книге написано:
«Если вы только изучаете Python, эта книга будет трудной для вас».
У вас может сложиться впечатление, что в каждом скрипте на Python должны использоваться специальные методы и приёмы метапрограммирования. Преждевременная абстракция так же плоха, как и преждевременная оптимизация.
Опытные программисты на Python извлекут из этой книги большую пользу.
А мы поможем вам прокачать скиллы или с самого начала освоить профессию в IT, актуальную в любое время:
Краткий каталог курсов и профессий
PEP 8, иногда обозначаемый PEP8 или PEP-8, представляет собой документ, содержащий рекомендации по написанию кода на Python. Он был составлен в 2001 году Гвидо ван Россумом, Барри Варшавой и Ником Когланом. Основная цель PEP 8 – улучшить читабельность и логичность кода на Python.
PEP расшифровывается как Python Enhancement Proposal («Предложение по усовершенствованию Python»), и их несколько. PEP — это документ для сообщества, который описывает новые функции, предлагаемые для Python, и содержит такие аспекты языка, как дизайн и стиль.
В цикле из трех статей мы разберем основные принципы, изложенные в PEP 8. Эти статьи предназначены для новичков и программистов среднего уровня, поэтому мы не будем затрагивать некоторые из наиболее сложных тем. Вы можете изучить их самостоятельно, прочитав полную документацию по PEP 8 .
Комментарии к блокам кода
Используйте блочные (т.е. многострочные) комментарии, чтобы задокументировать небольшой фрагмент кода. Такие комментарии полезны, когда вам нужно написать несколько строк кода для выполнения одного действия, например, для импорта данных из файла или обновления записи в базе данных. Они важны, поскольку помогают другим понять цель и функциональность данного блока кода.
PEP 8 предлагает следующие правила для написания комментариев к блокам кода:
Вот комментарий блока, объясняющий назначение цикла for . Обратите внимание, что предложение переносится на новую строку, чтобы сохранить ограничение в 79 символов:
Иногда, если код очень технический, необходимо использовать более одного абзаца в комментарии блока:
Если вы сомневаетесь в том, какой тип комментария вам подходит, зачастую можно остановиться именно на блочных. Прибегайте к ним почаще и не забывайте обновлять, если вносите изменения в свой код!
Максимальная длина строки и разрыв строки
PEP 8 предлагает ограничение на длину строк в 79 символов. Такая длина позволяет открывать несколько файлов рядом друг с другом, а также избегать переноса строк.
Конечно, не все предложения возможно вместить в 79 или менее символов. В PEP 8 очерчивает способы написать длинное предложение, заняв несколько строк.
Если код заключен в круглые, квадратные или фигурные скобки, Python «поймет», что это одно предложение:
Также, если невозможно дописать код в одну строку, вы можете использовать обратную косую черту для разрыва строк:
Однако, если вы можете продолжить писать в одну строку, вам следует это сделать.
Если разрыв строки должен произойти около бинарных операторов, таких как + и * , он должен произойти перед оператором. Это правило происходит из математики. Математики согласны с тем, что прерывание перед бинарными операторами улучшает читаемость. Сравните следующие два примера.
Разрыв перед бинарным оператором:
Вы можете сразу увидеть, какая переменная прибавляется или вычитается, поскольку оператор находится рядом с переменной, над которой выполняется операция.
Теперь давайте посмотрим на пример разрыва после бинарного оператора:
Здесь сложнее разглядеть, какая переменная добавляется, а какая вычитается.
Прерывание строки перед бинарными операторами дает более читаемый код, поэтому PEP 8 это поощряет.
Если вы переходите на новую строку после бинарного оператора, но делаете так последовательно во всем документе (проекте), это по-прежнему соответствует PEP 8. Но всё же рекомендуется первый вариант.
Комментарии
«Если реализацию сложно объяснить – идея точно плоха», — Дзен Python.
Документирование кода помогает разобраться в нем как вашим коллегам, так и вам самому. Поэтому по мере написания кода необходимо использовать комментарии. Из комментария должно быть понятно, что делает данный фрагмент кода и как он относится к остальной части программы.
Вот некоторые ключевые моменты, которые следует помнить при добавлении комментариев:
- Ограничьте длину строки комментариев и документации 72 символами.
- Используйте полные предложения, начинайте их с заглавной буквы.
- Не забывайте обновлять комментарии при изменении кода.
1. Подружитесь с PEP8
PEP8 — это официальное руководство по стилю кода Python. PEP расшифровывается как Python Enhancement Proposal («Предложение по улучшению Python»). Это документы, предлагающие новые особенности языка. Они образуют официальную документацию особенности языка, принятие или отклонение которой обсуждается в сообществе Python. Следование PEP8 не сделает код абсолютно «питоническим», но способствует узнаваемости кода для многих Python-разработчиков.
В PEP8 решаются вопросы, связанные с символами пробелов. Например, использование четырёх пробелов для отступа вместо символа табуляции или максимальной длиной строки: согласно PEP8, это 79 символов, хотя данная рекомендация, вероятно, самая игнорируемая.
Первое, что стоит усвоить из PEP8 новичкам, — это рекомендации и соглашения по именованию. Например, следует писать имена функций и переменных в нижнем регистре и с подчёркиваниями между словами lowercase_with_underscores:
Имена классов следует писать с прописными первыми буквами слов и без пробелов, вот так: CapitalizedWords:
Константы записывайте в верхнем регистре и с подчёркиваниями между словами: UPPER_CASE_WITH_UNDERSCORES:
В PEP8 изложены рекомендации по пробелам: как использовать их с операторами, аргументами и именами параметров функций и для разбиения длинных строк. Хотя эти рекомендации можно освоить, годами практикуясь в чтении и написании совместимого с PEP8 кода, многое всё равно пришлось бы запоминать.
Запоминать все соглашения PEP8 не нужно: найти и устранить проблемы PEP8 в коде могут помочь такие инструменты, как flake8. Установите flake8 с помощью pip:
flake8 можно использовать как приложение командной строки для просмотра файла Python на предмет нарушений стиля. Допустим, есть файл myscript.py с таким кодом:
При запуске на этом коде flake8 сообщает, как и где именно нарушается стиль:
В каждой выводимой строке flake8 сообщается, в каком файле и в какой строке проблема, в каком столбце строки начинается ошибка, номер ошибки и её описание. Используйте эти обозначения, flake8 можно настроить на игнорирование конкретных ошибок:
Как читать вывод flake8
Для проверки качества кода с помощью flake8 вы даже можете настроить редакторы, например VS Code. Пока вы пишете код, он постоянно проверяется на нарушения PEP8. Когда обнаруживается проблема, во flake8 под частью кода с ошибкой появляется красная волнистая линия, найденные ошибки можно увидеть во вкладке встроенного терминала Problems:
Проверки flake8 в Visual Studio Code
flake8 — отличный инструмент для поиска связанных с нарушением PEP8 ошибок, но исправлять их придётся вручную. А значит, будет много работы. К счастью, весь процесс автоматизируемый. Автоматически форматировать код согласно PEP можно с помощью инструмента под названием Black.
Конечно, рекомендации PEP8 оставляют много возможностей для выбора стиля, и в black многие решения принимаются за вас. Вы можете соглашаться с ними или нет. Конфигурация black минимальна.
Установите black c помощью pip:
После установки командой black --check можно посмотреть, будут ли black изменять файл:
Чтобы увидеть разницу после изменений, используйте флаг --diff:
Чтобы автоматически отформатировать файл, передайте его имя команде black:
Чтобы проверить совместимость с PEP8, снова запустите flake8 и посмотрите на вывод:
При работе с black следует иметь в виду, что максимальная длина строки по умолчанию в нём — это 88 символов. Это противоречит рекомендации PEP8 о 79 символах, поэтому при использовании black в отчёте flake8 вы увидете ошибки о длине строки.
Многие разработчики Python используют 88 знаков вместо 79, а некоторые — строки ещё длиннее. Можно настроить black на 79 символов, или flake8 — на строки большей длины.
Важно помнить, что PEP8 — это лишь набор рекомендаций, хотя многие программисты на Python относятся к ним серьёзно. PEP8 не применяется в обязательном порядке. Если в нём есть что-то, с чем вы категорически не согласны, вы вправе это игнорировать! Если же вы хотите строго придерживаться PEP8, инструменты типа flake8 и black сильно облегчат вам жизнь.
2. Избегайте циклов в стиле C
В таких языках, как C или C++, отслеживание индексной переменной при переборе массива — обычное дело. Поэтому программисты, которые перешли на Python из C или C++, при выводе элементов списка нередко пишут:
Вместо итерации можно перебрать все элементы списка сразу:
Этим вторая рекомендация не ограничивается: она намного глубже простого перебора элементов списка. Такие идиомы Python, как списковые включения, встроенные функции (min(), max() и sum()) и методы объектов, может помочь вывести ваш код на новый уровень.
Когда избегать добавления пробелов
В некоторых случаях добавление пробелов может затруднить чтение кода. Слишком много пробелов может сделать код слишком разреженным и трудным для понимания. PEP 8 дает четкое описание примеров, когда пробелы неуместны.
Самое важное место, где следует избегать пробелов, – это конец строки. Это называется завершающим пробелом (trailing whitespace). Такой пробел невидим и может приводить к ошибкам, которые трудно отследить.
В следующем списке перечислены некоторые случаи, когда вам не следует добавлять пробелы:
- Сразу после открывающей скобки и непосредственно перед закрывающей:
- Для отделения запятой, точки с запятой или двоеточия:
- Перед открывающей скобкой, с которой начинается список аргументов вызова функции:
- Перед открывающей скобкой, с которой начинается индекс или срез:
- Между запятой и закрывающей круглой скобкой:
- Чтобы выровнять операторы присваивания:
Убедитесь, что в вашем коде нет завершающих пробелов. Есть и другие случаи, когда PEP 8 не рекомендует добавлять лишние пробелы, например, непосредственно после открывающей и перед закрывающей скобкой.
Используйте в if-блоках тот факт, что пустые последовательности ложны
Если вы хотите проверить, пуст ли список, у вас может возникнуть соблазн проверить длину списка. Если список пуст, его длина равна 0, что эквивалентно False при использовании в операторе if . Вот пример:
Однако в Python любой пустой список, строка или кортеж является False . Таким образом, мы можем предложить более простую альтернативу приведенному выше коду:
Хотя в обоих примерах будет выведено, что список пуст, второй вариант проще, поэтому PEP 8 поддерживает его.
3. Используйте правильную структуру данных
Большая роль при написании чистого, питонического кода для конкретной задачи отводится выбору подходящей структуры данных. Python называют языком «с батарейками в комплекте». Некоторые батарейки из комплекта Python — это эффективные, готовые к применению структуры данных.
Используйте словари для быстрого поиска
Вот CSV-файл clients.csv с данными по клиентам:
Нужно написать программу, где в качестве входных данных принимается адрес электронной почты, а выводится номер телефона клиента с этой почтой, если такой клиент существует. Как бы вы это сделали?
Используя объект DictReader из модуля csv, можно прочитать каждую строку файла как словарь:
Но есть проблема: перебор списка клиентов неэффективен. Если в файле много клиентов, на поиск клиента с совпадающим адресом почты у программы может уйти много времени. А сколько теряется времени, если такие проверки проводятся часто!
Более питонически сопоставить клиентов с их почтами, а не хранить клиентов в списке. Для этого отлично подойдёт словарное включение:
Словарные включения очень похожи на списковые включения:
Я начинаю с создания пустого словаря:
<>.
Затем помещаю туда разделённую двоеточием пару «ключ — значение»:
.
Вот это словарное включение, преобразованное в цикл for:
С этим словарём clients вы можете найти телефон клиента по его почте без циклов:
Этот код не только короче, но и намного эффективнее перебора списка циклом. Но есть проблема: если в clients нет клиента с искомой почтой, поднимается ошибка KeyError:
Поэтому, если клиент не найден, можно перехватить KeyError и вывести значение по умолчанию:
Но более питонически применять метод словаря .get(). Если пара с ключом существует, этот метод возвращает значение пары, иначе возвращается None:
Сравним решения выше:
Питонический код короче, эффективнее и не менее удобен для восприятия.
Выводы
Если читателям будет интересно, то в следующей статье я опишу как в автоматическом режиме искать ошибки в коде.
Новички в Python часто спрашивают, как писать питонический код. Проблема — расплывчатое определение слова "питонический". Подробным материалом, в котором вы найдёте ответы на вопрос выше и три полезные книги, делимся к старту курса по Fullstack-разработке на Python.
Что значит «питонический»?
Python более 30 лет. За это время накоплен огромный опыт его применения в самых разных задачах. Этот опыт обобщался, и возникали лучшие практики, которые обычно называют «питоническим» кодом.
Философия Python раскрывается в The Zen of Python Тима Питерса, доступной в любом Python по команде import this в REPL:
Начинающих в Python больше всего раздражает красота Zen of Python. В Zen передаётся дух того, что значит «питонический» — и без явных советов. Вот первый принцип дзена Python: «Красивое лучше, чем уродливое». Согласен на 100%! Но как сделать красивым мой некрасивый код? Что это вообще такое — «красивый код»?
Сколь бы ни раздражала эта неоднозначность, именно она делает Zen of Python таким же актуальным, как и в 1999 году, когда Тим Питерс написал этот набор руководящих принципов. Они помогают понять, как отличать питонический и непитонический код, и дают ментальную основу принятия собственных решений.
Каким же будет определение слова «питонический»? Лучшее найденное мной определение взято из ответа на вопрос «Что означает «питонический» В этом ответе питонический код описывается так:
Код, где правилен не только синтаксис, но соблюдаются соглашения сообщества Python, а язык используется так, как он должен использоваться.
Из этого делаем два ключевых вывода:
Слово «питонический» связано скорее со стилем, чем с синтаксисом. Хотя идиомы Python часто имеют последствия за рамками чисто стилистического выбора, в том числе повышение производительности кода.
То, что считается «питоническим», определяется сообществом Python.
Итак, у нас сложилось хотя бы какое-то представление о том, что имеют в виду программисты на Python, называя код «питоническим». Рассмотрим три конкретных и доступных способа написания более питонического кода.
Английский для программистов
Наш телеграм канал с тестами по английскому языку для программистов. Английский это часть карьеры программиста. Поэтому полезно заняться им уже сейчас
Стандарты и рекомендации к оформлению
Если для повышения скорости исполнения кода можно использовать разные подходы, хотя эти подходы очень индивидуальны, то для форматирования текста существует прям slyle guide — это pep8. Далее его буду называть «стандарт».
Почитать про стандарт можно здесь, на русском языке можно здесь
Pep8 весьма обширный и позволяет программисту писать РЕАЛЬНО читаемый код.
- максимальную длину строк кода и документации
- кодировки файлов с исходным кодом
- рекомендации как правильно оформлять комментарии
- соглашения именования функций/классов, аргументов
- и многое другое
Отступ после разрывов строки
Когда вы используете продолжение строки, чтобы длина строки не превышала 79 символов, полезно использовать отступ для улучшения читаемости. Это позволяет различать две строки кода и одну строку кода, размещенную на двух строчках. Можно использовать два стиля отступа.
Первый из них — выровнять блок с отступом по открывающей скобке:
Иногда может оказаться, что для выравнивания по открывающей скобке требуется всего 4 пробела. Это часто происходит в операторах if , которые охватывают несколько строк, поскольку if , пробел и открывающая скобка составляют 4 символа. В этом случае бывает сложно определить, где внутри оператора if начинается вложенный блок кода:
В этом случае PEP 8 предоставляет две альтернативы для улучшения читаемости.
Во-первых, можно добавлять комментарии после последнего условия. Из-за подсветки синтаксиса в большинстве редакторов это отделит условия от вложенного кода:
Во-вторых, можно сделать дополнительный отступ в продолжении строки:
Альтернативный вариант отступа после разрыва строки – висячий отступ. Это типографский термин, означающий, что каждая строка, кроме первой в абзаце или цитате, имеет отступ. Вы можете использовать такой отступ для визуального представления продолжения строки кода. Вот пример:
Замечание. Если вы используете висячий отступ, в первой строке не должно быть аргументов. Следующий пример не соответствует требованиям PEP 8:
В данном случае потребуется дополнительный отступ, чтобы отличить продолжающуюся строку от кода, содержащегося внутри функции. Следующий пример трудно прочитать, потому что код внутри функции находится на том же уровне отступа, что и продолженные строки:
Вместо этого лучше использовать двойной отступ в продолжении строки. Это поможет вам различать аргументы функции и тело функции, улучшая читаемость:
Когда вы пишете код, отвечающий требованиям PEP 8, ограничение в 79 символов вынуждает вас добавлять разрывы строк. Для лучшей читаемости нужно делать отступ в продолжении строки, чтобы показать, что это одна строка. Это можно сделать двумя способами. Первый — выровнять блок с отступом по открывающей скобке. Второй — использовать висячий отступ. Метод отступа после разрыва строки можно выбрать самостоятельно.
Встроенные комментарии
Встроенные (inline) комментарии объясняют один оператор в фрагменте кода. Они полезны, чтобы напомнить вам или объяснить другим, почему необходима определенная строка. Вот что о них говорит PEP 8:
Ниже приведен пример встроенного комментария:
Порой кажется, что без встроенного комментария не обойтись, но иногда проблему решает просто удачное название переменной. Вот пример:
Здесь встроенный комментарий дает дополнительную информацию. Однако использование x в качестве имени переменной для имени человека — плохая практика. Если вы переименуете переменную, то отпадёт и необходимость во встроенном комментарии:
Наконец, встроенные комментарии, подобные этим, являются плохой практикой, поскольку они поясняют очевидный и беспорядочный код:
Встроенные комментарии более конкретны, чем блочные, и их легко добавить, когда они не нужны, что приводит к беспорядку. Часто можно обойтись одними блочными комментариями, поэтому, если вы не уверены, что вам нужен встроенный комментарий, пользуйтесь только многострочными, и ваш код с большей вероятностью будет соответствовать PEP 8.
Заключение
Теперь вы знаете, как писать качественный, читаемый код на Python, используя рекомендации, изложенные в PEP 8. Хотя эти рекомендации могут показаться педантичными, следование им может действительно улучшить ваш код. Это особенно важно, когда вы собираетесь делиться своим кодом с потенциальными работодателями или соавторами.
Из этой серии статей вы узнали:
- что такое PEP 8 и почему он существует;
- почему вы должны стремиться писать код согласно PEP 8;
- как написать код, соответствующий PEP 8.
Вдобавок ко всему, вы также увидели, как использовать линтеры и автоформаттеры для проверки вашего кода на соответствие рекомендациям PEP 8.
Размещение кода
«Красивое лучше уродливого», — Дзен Python.
Расположение строк вашего кода играет огромную роль в его читабельности. В этом разделе вы узнаете, как добавлять отступы, чтобы улучшить читаемость кода. Вы также узнаете, как использовать ограничение в 79 символов в строке, рекомендованное в PEP 8.
Автоформаттеры
Автоформаттеры – это программы, которые автоматически реорганизуют ваш код для соответствия PEP 8. Одна из таких программ — black . Она автоматически форматирует код для приведения его в соответствие с большинством правил PEP 8. Единственное, она ограничивает длину строки до 88 символов, а не до 79, как рекомендовано стандартом. Однако вы можете изменить это, добавив флаг командной строки, как в примере ниже.
Установите black с помощью pip. Для запуска требуется Python 3.6+:
Его можно запустить из командной строки, как и в случае с линтерами. Допустим, вы начали со следующего кода, который не соответствует PEP 8, в файле с именем code.py:
Затем вы можете запустить следующую команду через командную строку:
code.py будет автоматически приведён к следующему виду:
Если вы хотите изменить ограничение длины строки, можно использовать флаг --line-length :
Работа двух других автоформаттеров – autopep8 и yapf – аналогична работе black .
О том, как использовать эти инструменты, хорошо написано в статье Python Code Quality: Tools & Best Practices Александра ван Тол.
В предыдущей статье о PEP 8 мы узнали, что это за стандарт и в чем его важность. Также мы рассмотрели, каким образом можно привести код в соответствие с этим стандартом. В этой статье переходим к разбору конкретных рекомендаций по оформлению кода на Python. Мы рассмотрим, как выбирать имена, как делать вертикальные и горизонтальные отступы в коде, как переносить строки, где ставить закрывающие скобки.
Соглашения об именах
«Явное лучше неявного», — Дзен Python.
Когда вы пишете код на Python, вам нужно назвать множество вещей: переменные, функции, классы, пакеты и так далее. Выбор разумных имен сэкономит вам время и силы в дальнейшем. По названию вы сможете понять, что представляет собой определенная переменная, функция или класс. Вы также избежите использования неподходящих имен, которые могут привести к трудноисправляемым ошибкам.
Совет: никогда не используйте однобуквенные имена l, O или I, поскольку они могут быть ошибочно приняты за 1 и 0 при определённых шрифтах:
Стили именования
В таблице ниже описаны некоторые из распространенных стилей именования в коде на Python и указаны случаи, когда их следует использовать:
Тип | Соглашение о наименовании | Примеры |
---|---|---|
Функция | Используйте слово/слова в нижнем регистре. Отделяйте слова нижним подчёркиванием. | function, my_function |
Переменная | Используйте одну букву, слово или слова в нижнем регистре. Для удобства чтения разделяйте слова нижним подчеркиванием. | x, var, my_variable |
Класс | Каждое слово начинайте с заглавной буквы. Не разделяйте слова подчеркиванием. Этот стиль называется Pascal Case. | Model, MyClass |
Метод | Используйте слово/слова в нижнем регистре. Для удобства чтения разделяйте слова подчеркиванием. | class_method, method |
Константа | Используйте одну букву, слово или слова в верхнем регистре. Для удобства чтения разделяйте слова подчеркиванием. | CONSTANT, MY_CONSTANT, MY_LONG_CONSTANT |
Модуль | Используйте короткое слово/слова в нижнем регистре. Для удобства чтения разделяйте слова подчеркиванием. | module.py, my_module.py |
Пакет | Используйте короткие слова или слова в нижнем регистре. Не разделяйте слова подчеркиванием. | package, mypackage |
Придерживайтесь выбранного стиля во всем проекте, и ваш код станет более читабельным. Также будьте осторожны при выборе букв и слов.
Стиль нейминга, безусловно, важен, но кроме того нужно тщательно выбирать сами имена. Ниже приведены несколько советов о том, как делать это максимально эффективно.
Проблемы форматирования
Идеального форматирования кода не существует. Для каждого языка стоит подстраиваться под общепринятые правила оформления кода. Да что говорить, если среди новичков С++ еще до сих пор войны по поводу ставить скобки на следующей строке или нет.
Для python'а основными проблемами форматирования является «C стиль». Не редко в рассматриваемый язык приходят из С-подобных языков, а для них свойственно писать с символами ")(;".
Символы не единственная проблема, есть еще и проблема избыточности написания конструкций. Питон, в отличие от Java, менее многословен и чтобы к этому привыкнуть у новичков уходит большое количество времени.
Это две основные проблемы, которые встречаются чаще всего.
Куда поставить закрывающую скобку
Продолжение строк позволяет нам разрывать строки внутри кавычек и различных скобок. О закрывающей скобке легко забыть, но важно поместить ее в разумное место. В противном случае читатель может запутаться. PEP 8 предлагает два варианта положения закрывающей скобки в подразумеваемых продолжениях строк.
Можно выровнять закрывающую скобку по первому не пробельному символу предыдущей строки:
А можно совместить закрывающую скобку с первым символом строки, с которой начинается конструкция:
Оба варианта совершенно равноправны. Но, как всегда, ключевым моментом здесь является последовательность, поэтому постарайтесь придерживаться какого-то одного из указанных методов.
В следующей статье о PEP 8 мы разберем правила оформления комментариев, использование пробелов и выбор операторов и методов.
Третья статья цикла, посвященного стандарту PEP 8. В первой статье мы рассмотрели, в чем вообще смысл стандартов и соглашений, что такое PEP 8 и какие инструменты помогают нам придерживаться выбранного стиля оформления кода. Во второй статье мы более подробно остановились на вопросах размещения кода, нейминга, отступов. Сейчас давайте остановимся на правилах оформления комментариев, использовании пробелов и рекомендациях по написанию более чистого кода.
Табуляция vs. пробелы
Как упоминалось выше, для отступа кода следует использовать пробелы вместо табуляции. Вы можете настроить параметры в текстовом редакторе таким образом, чтобы выводить 4 пробела вместо символа табуляции при нажатии клавиши Tab.
Если вы используете Python 2 и применяли сочетание табуляции и пробелов для отступа в коде, вы не увидите ошибок при попытке запустить этот код. Чтобы проверить согласованность, можно добавить флаг - t при запуске кода на Python 2 из командной строки. Если есть проблемы с использованием табуляции и пробелов, интерпретатор выдаст предупреждения:
Если вместо этого вы используете флаг -tt , интерпретатор будет выдавать ошибки вместо предупреждений, и ваш код не будет запущен. Преимущество использования этого метода заключается в том, что интерпретатор сообщает вам, в чем заключаются несоответствия:
Python 3 не позволяет смешивать табуляцию и пробелы. Поэтому, если вы используете Python 3, эти ошибки выдаются автоматически:
При написании кода на Python для создания отступов можно использовать табуляцию, а можно и пробелы. Но если речь идет о Python 3, вы должны быть последовательны в своем выборе. В противном случае ваш код не запустится. PEP 8 рекомендует всегда использовать 4 последовательных пробела для обозначения отступа.
Английский для программистов
Наш телеграм канал с тестами по английскому языку для программистов. Английский это часть карьеры программиста. Поэтому полезно заняться им уже сейчас
Линтеры
Линтеры – это программы, которые анализируют код, помечают ошибки и предлагают способы их исправления. Они особенно полезны как расширения редактора, поскольку выявляют ошибки и стилистические проблемы во время написания кода.
Вот пара лучших линтеров для кода на Python:
pycodestyle
Это инструмент для проверки вашего кода на соответствие некоторым стилевым соглашениям в PEP8.
Установите pycodestyle с помощью pip:
Вы можете запустить pycodestyle из терминала, используя следующую команду:
flake8
Это инструмент, который сочетает в себе отладчик, pyflakes и pycodestyle.
Установите flake8 с помощью pip:
Запустите flake8 из терминала, используя следующую команду:
Замечание: Дополнительная строка в выводе указывает на синтаксическую ошибку.
Из данной серии статей вы узнаете:
- как писать Python-код, соответствующий PEP8;
- какие доводы лежат в основе рекомендаций, изложенных в PEP8;
- как настроить среду разработки так, чтобы вы могли начать писать код на Python по PEP8.
Рекомендации по программированию
«Простое лучше сложного», — Дзен Python.
Мы часто обнаруживаем, что в Python (как и в любом другом языке программирования) бывает несколько способов выполнить одно и то же действие. В этом разделе мы рассмотрим несколько предложений из PEP 8, призванных устранить эту двусмысленность и сохранить согласованность.
Читайте также: