python правила оформления кода
Правила оформления Python-кода
1. Отступы
Рекомендуется использовать 4 пробела на каждый уровень отступа. Python 3 запрещает смешивание табуляции и пробелов в отступах. Код, в котором используются и те, и другие типы отступов, должен быть исправлен так, чтобы отступы в нем были расставлены только с помощью пробелов.
2. Точки с запятой
Не разделяйте ваши строки с помощью точек с запятой и не используйте точки с запятой для разделения команд, находящихся на одной строке.
3. Скобки
Используйте скобки экономно. Не используйте их с выражением return или с условной конструкцией, если не требуется организовать перенос строки. Однако скобки хорошо использовать для создания кортежей.
4. Пробелы в выражениях и инструкциях
4.1 Пробелы и скобки
4.1.1 Не ставьте пробелы внутри каких-либо скобок (обычных, фигурных и квадратных).
4.1.2 Никаких пробелов перед открывающей скобкой, которая начинает список аргументов, индекс или срез.
Хорошо Плохо Хорошо Плохо
4.2 Пробелы рядом с запятой, точкой с запятой и точкой
4.2.1 Перед запятой, точкой с запятой либо точкой не должно быть никаких пробелов. Используйте пробел после запятой, точки с запятой или точки (кроме того случая, когда они находятся в конце строки).
4.3 Пробелы вокруг бинарных операторов
4.3.2 Не используйте более одного пробела вокруг оператора присваивания (или любого другого оператора) для того, чтобы выровнять его с другим.
5. Длина строк
Ограничивайте длину строк 79 символами (а длину строк документации и комментариев — 72 символами). В общем случае не используйте обратный слеш в качестве перехода на новую строку. Используйте доступное в Python явное объединение строк посредством круглых и фигурных скобок. Если необходимо, можно добавить дополнительную пару скобок вокруг выражения.
Если ваш текст не помещается в одну строку, используйте скобки для явного объединения строк.
Что касается длинных URL в комментариях, то располагайте их, если это необходимо, на одной строке.
Обратный слеш иногда используется. Например, с длинной конструкцией with для переноса блока инструкций.
6. Пустые строки
Отделяйте функции (верхнего уровня, не функции внутри функций) и определения классов двумя пустыми строками. Определения методов внутри класса отделяйте одной пустой строкой. Две пустые строки должны быть между объявлениями верхнего уровня, будь это класс или функция. Одна пустая строка должна быть между определениями методов и между объявлением класса и его первым методом.
Используйте (без энтузиазма) пустые строки в коде функций, чтобы отделить друг от друга логические части.
Python расценивает символ control+L как незначащий (whitespace), и вы можете использовать его, потому что многие редакторы обрабатывают его как разрыв страницы — таким образом, логические части в файле будут на разных страницах. Однако не все редакторы распознают control+L и могут на его месте отображать другой символ.
7. Имена
Имена, которых следует избегать:
7.1 Имена функций
Имена функций должны состоять из маленьких букв, а слова разделяться символами подчеркивания — это необходимо, чтобы увеличить читабельность.
Стиль mixedCase допускается в тех местах, где уже преобладает такой стиль — для сохранения обратной совместимости.
7.2 Имена модулей и пакетов
Модули должны иметь короткие имена, состоящие из маленьких букв. Можно использовать символы подчёркивания, если это улучшает читабельность. То же самое относится и к именам пакетов, однако в именах пакетов не рекомендуется использовать символ подчёркивания.
Так как имена модулей отображаются в имена файлов, а некоторые файловые системы являются нечувствительными к регистру символов и обрезают длинные имена, очень важно использовать достаточно короткие имена модулей — это не проблема в Unix, но, возможно, код окажется непереносимым в старые версии Windows, Mac, или DOS.
7.3 Имена классов
Все имена классов должны следовать соглашению CapWords почти без исключений.
Иногда вместо этого могут использоваться соглашения для именования функций, если интерфейс документирован и используется в основном как функции.
Обратите внимание, что существуют отдельных соглашения о встроенных именах: большинство встроенных имен — одно слово (либо два слитно написанных слова), а соглашение CapWords используется только для именования исключений и встроенных констант.
Так как исключения являются классами, к исключениями применяется стиль именования классов. Однако вы можете добавить Error в конце имени (если, конечно, исключение действительно является ошибкой).
7.4 Имена констант
Константы обычно объявляются на уровне модуля и записываются только заглавными буквами, а слова разделяются символами подчеркивания.
8. Комментарии
Комментарии, противоречащие коду, хуже, чем отсутствие комментариев. Всегда исправляйте комментарии, если меняете код!
Комментарии должны быть законченными предложениями. Если комментарий — фраза или предложение, первое слово должно быть написано с большой буквы, если только это не имя переменной, которая начинается с маленькой буквы (никогда не отступайте от этого правила для имен переменных).
Ставьте два пробела после точки в конце предложения.
Если вы — программист, не говорящий по-английски, то всё равно следует использовать английский язык для написания комментариев. Особенно, если нет уверенности на 120% в том, что этот код будут читать только люди, говорящие на вашем родном языке.
8.1 Блоки комментариев
Блок комментариев обычно объясняет код (весь или только некоторую часть), идущий после блока, и должен иметь тот же отступ, что и сам код. Каждая строчка такого блока должна начинаться с символа # и одного пробела после него (если только сам текст комментария не имеет отступа).
8.2 Комментарии в строке с кодом
Старайтесь реже использовать подобные комментарии.
Такой комментарий находится в той же строке, что и инструкция. «Встрочные» комментарии должны отделяться хотя бы двумя пробелами от инструкции. Они должны начинаться с символа # и одного пробела.
Комментарии в строке с кодом не нужны и только отвлекают от чтения, если они объясняют очевидное.
8.3 Строки документации
Соглашения о написании хорошей документации (docstrings) зафиксированы в PEP 257.
Очень важно, чтобы закрывающие кавычки стояли на отдельной строке. А еще лучше, если перед ними будет ещё и пустая строка.
Для однострочной документации можно оставить «»» на той же строке.
9. Циклы
9.1 Циклы по спискам
Если нам необходимо в цикле пройти по всем элементам списка, то хорошим тоном (да и более читаемым) будет такой способ:
И хотя бывалые программисты или просто любители C могут использовать и такой код, это моветон.
А если нужно пройти по списку задом наперед, то лучше всего использовать метод reversed:
Вместо того чтобы писать избыточный код, который и читается-то не очень внятно.
9.2 Циклы по списку чисел
Если есть необходимость пройти в цикле по ряду чисел, то метод range будет намного приемлемее, как минимум потому, что этот метод потребляет намного меньше памяти, чем вариант в блоке «Плохо». А представьте, что у вас ряд из трёх миллиардов последовательных чисел!
9.3 Циклы по спискам с индексами
Метод enumerate позволяет получить сразу индекс и значение из списка, что, во-первых, предоставляет множество возможностей для дальшнейшего проектирования, а во-вторых, такой код легче читается и воспринимается.
9.4 Циклы по двум спискам
Используя метод zip, мы получаем из двух списков один список кортежей, что более удобно для дальнейшего использования и требует меньше памяти. Да и просто этот вариант более элегантный.
10. Импорты
Каждый импорт, как правило, должен быть на отдельной строке.
В то же время, можно писать так:
Импорты всегда располагаются в начале файла, сразу после комментариев уровня модуля, строк документации, перед объявлением констант и объектов уровня модуля. Импорты должны быть сгруппированы в порядке от самых простых до самых сложных:
Наряду с группированием, импорты должны быть отсортированы лексикографически, нерегистрозависимо, согласно полному пути до каждого модуля.
Рекомендуется абсолютное импортирование, так как оно обычно более читаемо и ведет себя лучше (или, по крайней мере, даёт понятные сообщения об ошибках), если импортируемая система настроена неправильно (например, когда каталог внутри пакета заканчивается на sys.path ).
Тем не менее, явный относительный импорт является приемлемой альтернативой абсолютному импорту, особенно при работе со сложными пакетами, где использование абсолютного импорта было бы излишне подробным.
Следует избегать шаблонов импортов ( from import * ), так как они делают неясным то, какие имена присутствуют в глобальном пространстве имён, что вводит в заблуждение как читателей, так и многие автоматизированные средства.
Рекомендуем также ознакомиться с полной версией соглашения о том, как писать код на Python (PEP 8)
Советы Google по кодированию на языке Python. Часть вторая: советы по форматированию исходного кода
Python Style Rules
Точки с запятой
Длина строки
Исключения
Когда Ваш текст не помещается в одну строку, используйте скобки для явного объединения строк.
Что касается комментариев, располагайте длинный URL, если это необходимо, на одной строке.
Обратите внимание на отступ элемента в строке выше (смотрите раздел про отступы, чтобы получить разъяснения).
Скобки
Не используйте их (скобки) с выражением return или с условной конструкцией, если не требуется организовать перенос строки. (Смотрите выше). Однако скобки хорошо использовать для создания кортежей.
Отступы
В случае, когда вы подразумеваете перенос строки, вы должны выровнять каждый перенесенный элемент по вертикали так, как описано в примере о длине строк, либо используя отступ в 4 пробела, в этом случае не должно быть ни одного аргумента на первой строке.
Пустые строки
Пробелы
Никаких пробелов внутри каких-либо скобок.
Хорошо: spam(ham[1],
Плохо: spam( ham[ 1 ], < eggs: 2 >, [ ] )
Никаких пробелов перед запятой, точкой с запятой, либо точкой. Используйте пробел после запятой, точки с запятой или точкой, исключая тот случай, когда они находятся в конце строки.
Комментарии
Будьте уверены в использовании правильного стиля для модуля, функции, метода или строкового комментария.
Строки документации.
Python имеет уникальный стиль комментирования — строки документации. Строка документации это строка, которая является первой конструкцией в пакете, модуле, классе или функции. Такие строки могут быть экспортированы автоматически с помощью атрибута объекта __doc__ и используются pydoc-ом. (Попробуйте запустить pydoc на своем модуле, чтобы увидеть как это выглядит.) Наше соглашение по строкам документации велит использовать три двойные кавычки для обрамления такой строки. Строки документации должны быть организованы как суммарная строка (одна физическая строка), сносящаяся по кол-ву символов, знаку вопроса или восклицательному знаку, следующим за пустой строкой, а затем остальные строки документации с позиции курсора в качестве первой кавычки первой строки. Ниже описано еще больше информации по оформлению строк документирования.
Модули
Каждый файл должен содержать в себе шаблон лицензии. Выберите подходящий шаблон лицензии для вашего проекта.(Например, Apache 2.0, BSD, LGPL, GPL).
Функции и методы
Классы
Классы должны иметь строку документации ниже своего объявления. Если Ваш класс имеет публичные атрибуты, они должны быть документированы тут же в разделе Attributes и следовать тому же стилю форматирования, что и раздел Args.
Блоки и инлайновые комментарии
Последнее место, которое должны иметь комментарии — это хитрые места в коде. Если Вы хотите пояснить их в Вашем следующем код-ревью, то вы должны прокомментировать их сейчас. Сложные операции, занимающие несколько строк документации перед ее выполнением. Неявные части должны иметь комментарий в конце строки.
Чтобы улучшить читаемость, такие комменарии должны находиться на расстоянии по меньшей мере 2-х пробелов от кода. С другой стороны, лучше вообще не описывайте код. Преположите, что человек, читающий данный код, знает Python (а не то, что вы пытались делать) лучше, чем Вы.
Классы
Это также касается вложенных классов.
Наследование от класса object необходимо, чтобы позволить свойствам работать правильно, и защитит Ваш код от возможной несовместимости с Python 3000. В нем так же определяются специальные методы, которые реализуют стандартную семантику объекта, например: __new__, __init__, __delattr__, __getattribute__, __setattr__, __hash__, __repr__, и __str__.
Строки
Используйте оператор % для форматирования строк, даже если все параметры являются строками. Тщательно взвесте использование оператора + взамен оператора %.
Избегайте использования операторов + и +=, чтобы сконкатенировать строку при помощи цикла, т.к. строки — это неизменяемый тип данных, такой подход создает ненужные объекты и увеличивает время работы по квадратичному, а не линейному закону. Вместо этого просто добавьте каждую подстроку в список и используйте метод join после того, как цикл завершится ( или записывайте каждую подстроку в буфер cStringIO.StringIO)
Используйте “”” для многострочных строк вместо “”. Заметьте, однако, что всегда лучше использовать явное объединение строк, т.к. многострочные строки не продолжаются до конца программы с таким же отступом.
Файлы и сокеты
Подобные циклу for объекты, которые не поддерживают конструкцию with и используют contextlib.closing()
Старый код, написанный под Python 2.5, может подключить возможность использования конструкции with при помощи импорта «from __future__ import with_statement«.
Комментарий TODO
Комментарии-TODO должны включать в себя строку TODO в начале каждого комментария, следующую за имменем, электронным адресом или другим идентификатором того, что лучше сможет обеспечить решение проблемы, указанной в скобках. Точка необязательна. Комментарий, объясняющий что там должно происходить, не требуется. Главная цель — это общий формат для TODO, который позволит быстро найти определенного челвоека, который сможет обеспечить более детальное описание проблемы. TODO не является залогом того, что человек решит данную проблему. Таким образом, когда Вы создаете TODO, он почти всегда содержит только Ваше имя.
Оформление импортов
Конструкции
Однако вы можете расположить результат текста на той же строке, на которой у Вас рапологается условие. Но это можно сделать только в том случае, когда все выражение помещается на одной строке. В частности, Вы никогда не сможете это сделать с конструкцией try/except, т.к. try и except не могут находиться в одной строке, и Вам доступно помещение в одну строку только с конструкцией if БЕЗ else.
Хорошо:
Контроль доступа
Именование
module_name, package_name, ClassName, method_name, ExceptionName, function_name, GLOBAL_CONSTANT_NAME, global_var_name, instance_var_name, function_parameter_name, local_var_name.
Стили основаны на рекоммендациях Гвидо:
Тип | Внешний | Внутренний |
Пакеты | lower_with_under | |
Модули | lower_with_under | _lower_with_under |
Классы | CapWords | _CapWords |
Исключения | CapWords | |
Функции | lower_with_under() | _lower_with_under() |
Глобальные/Внутриклассовые константы | CAPS_WITH_UNDER | _CAPS_WITH_UNDER |
Глобальные/Внутриклассовые переменные | lower_with_under | _lower_with_under |
Переменные экземпляра класса | lower_with_under | _lower_with_under (protected) or __lower_with_under (private) |
Имена методов | lower_with_under() | _lower_with_under() (protected) or __lower_with_under() (private) |
Аргументы функций/методов | lower_with_under | |
Локальные переменные | lower_with_under |
Даже когда файл создавался для того, чтобы быть импортированным, обычный импорт не должен иметь побочных эффектов в виде исполнения функциональной части скрипта. Основная функциональность должна быть заложена в функции main().
В Python, pychecker, pydoc и юнит тестах требуются импортируемые модули. Ваш код должен всегда проверять if __name__ == ‘__main__’ перед исполнением, что означает, что Ваш модуль не будет полностью исполнен при импортировании его в другую программу.
Весь код верхнего уровня будет исполнен, когда модуль будет импортирован. Будьте осторожны и не вызывайте функции, не создавайте объекта и не проводите другого вида операции, которые не должны будут выполняться, когда файл подвергнется проверке с помощью pychecker или будет собираться документация при помощи pydoc.
Заключительные слова
От переводчика
Благодарности
Огромное спасибо squaii за ревью и поиск ошибок.
Заключение
Форматирование Python-кода
Введение
Python, точнее его самый известный представитель CPython, не очень предназначен для каких-либо быстрых расчетов. Иначе говоря, производительность у него не такая уж хорошая. А вот скорость разработки и читаемости отличная.
О читаемости и пойдет речь, а точнее как ее увеличить.
Проблемы форматирования
Идеального форматирования кода не существует. Для каждого языка стоит подстраиваться под общепринятые правила оформления кода. Да что говорить, если среди новичков С++ еще до сих пор войны по поводу ставить скобки на следующей строке или нет.
Для python’а основными проблемами форматирования является «C стиль». Не редко в рассматриваемый язык приходят из С-подобных языков, а для них свойственно писать с символами «)(;».
Символы не единственная проблема, есть еще и проблема избыточности написания конструкций. Питон, в отличие от Java, менее многословен и чтобы к этому привыкнуть у новичков уходит большое количество времени.
Это две основные проблемы, которые встречаются чаще всего.
Стандарты и рекомендации к оформлению
Если для повышения скорости исполнения кода можно использовать разные подходы, хотя эти подходы очень индивидуальны, то для форматирования текста существует прям slyle guide — это pep8. Далее его буду называть «стандарт».
Почитать про стандарт можно здесь, на русском языке можно здесь
Pep8 весьма обширный и позволяет программисту писать РЕАЛЬНО читаемый код.
Автоматизируем форматирование
Если посмотреть сколько всяких правил в pep8, то можно сесть за рефакторинг надолго. Вот только это лениво, да и при написании нового кода сиравно будут какие-то ошибки правил. Для этого рассмотрим как же себе можно упростить жизнь.
Дабы иметь представление сколько ошибок оформления в коде, стоит использовать утилиту pep8.
У нее достаточный список параметров, который позволяет рекурсивно просмотреть все файлы в папках на предмет соответствия стандарту pep8.
Вывод утилиты примерно такой:
По нему можно однозначно понять: где ошибка и что случилось.
autopep8
Ошибки стандарта часто повторяются от файла в файлу. И возникает сильное желание исправление автоматизировать. В этом случае на арену выходит autopep8.
Как и pep8, он умеет самостоятельно определять ошибки, а также исправлять их. Список исправляемых ошибок форматирования можно найти здесь
Само использование autopep8 крайне простое и может выглядеть так:
После выполнения данной команды, утилита рекурсивно пойдет по подпапкам и начнет в самих же файлах исправлять ошибки.
autoflake
Тем самым будут рекурсивно почищены файлы в директории.
unify
Крайний, заключительный момент в редактировании кода — это строки. Кто-то любит их писать в одиночных апострофах, кто-то в двойных. Вот только и для этого существует рекомендации, а также и утилита, которая позволяет автоматически приводить в соответствие — unify
Использование:
Как и везде, утилита выполнит свое грязное дело рекурсивно для файлов в папке.
docformatter
Все время говорим о самом коде, а о комментариях еще ни разу не шло речи. Настало время — docformatter. Эта утилита помогает привести ваши docstring по соглашению PEP 257. Соглашение предписывает как следует оформлять документацию.
Использование утилиты ничуть не сложнее предыдущих:
А все вместе можно?
Выше описаны утилиты, их запуск можно добавить какой-нибудь bash скрипт под магическим названием clean.bash и запускать. А можно пойти и по другому пути и использовать wrapper над этими утилитами — pyformat
Выводы
Python-код легко читается, однако, есть способы сделать лапшу и из читаемого кода.
В данной статье были озвучены некоторые проблемы оформления кода, а также способы поиска этих проблем. Были рассмотрены несколько утилит, которые позволяют в автоматическом режиме убрать некоторые изъяны оформления кода.
Стоит озвучить вслух следующую рекомендацию при написании кода, которая универсальна для любого языка: более важным правилом оформлением, чем подобные pep8-документы — это постоянство стиля. Выбрали в каком стиле будете писать программу, в этом же и пишите весь код.
Если читателям будет интересно, то в следующей статье я опишу как в автоматическом режиме искать ошибки в коде.
Путеводитель по Python. Пишем великолепный код
Kenneth Reitz на PyCon в Австралии (2012)
Структурируйте свой проект
Под структурой мы подразумеваем решения, которые Вы приняли в отношении того, как Ваш проект сможет достичь поставленных целей. Мы должны рассмотреть как лучше использовать функциональные особенности языка Python, чтобы писать чистый и эффективный код. С практической точки зрения, понятие «структура» означает создание (написание) чистого когда в котором, логика и зависимости так же ясны как организация файлов и папок в файловой системе.
Какие функции должны быть перемещены в какие модули? Как пойдет поток данных через проект? Какие особенности и функции могут быть сгруппированы вместе и изолированы? Отвечая на подобные вопросы, Вы можете начать планировать как будет выглядеть готовый продукт.
В данном разделе мы внимательнее посмотрим на систему модулей и импортов в Python, т.к. они являются центральным элементом в обеспечении структурирования Вашего проекта. Затем, мы обсудим различные точки зрения о том, как построить код, который может быть расширен и надежно протестирован.
Структура решает
Благодаря тому, что импорты и модули обрабатываются в Python, сравнительно просто структурировать проект написанный на этом языке. Слово «просто», в данном контексте означает, что Вы не будете создавать лишних ограничений, и то, что модель импортируемого модуля легко понять. Таким образом, Вам остается сконцентрироваться на чисто архитектурной задаче, а именно трудиться над созданием различных частей Вашего проекта и их взаимодействии.
Модули
Модули в Python являются одним из основных слоев абстракции которые доступны, и, вероятно, являются наиболее нативными для языка. Уровни абстракции позволяют разделить код на части обрабатывающие соответствующие данные и содержащие какой-либо функционал.
Чтобы придерживаться стиля руководства, старайтесь давать модулям короткие имена, содержащие только буквы нижнего регистра и уверяться, что Вы не используете специальные символы, такие как точка (.) или знак вопроса (?). Так как имя файла подобное my.spam.py, Вы должны избегать. Именование таким образом будет мешать Python искать модули.
В данном примере Python ожидает найти » spam.py » в папке по имени » my «, которой не существует. Существует пример того, как точечная нотация должна быть использована в документах Python.
Помимо некоторых ограничений именования, ничего больше не требуется файлу чтобы стать Python-модулем, но механизм импорта необходимо понимать для того, чтобы использовать эту концепцию должным образом и избежать некоторых проблем.
После того, как module.py будет найден, интерпретатор Python выполнит модуль в изолированной области видимости. Любое объявление верхнего уровня в файле module.py будет выполнено, включая вложенные импорты, если таковые имеются. Объявления функций и классов сохранятся в словарь модуля.
Затем переменные модуля, функции и классы будут доступны для вызова через пространство имен модуля — центральное понятие в программировании, которое особенно мощно и полезно в языке Python.
Во многих языках, файл включается напрямую используя препроцессор чтобы найти весь код в файле и «скопировать» его в код вызывающего модуля. Это отличается от поведения языка Python, в котором подключаемый код изолирован в области видимости своего модуля, что означает, что Вы можете не беспокоиться о том, что включение кода может иметь нежелательные последствия, например, переопределение существующих функций с тем же именем.
Использование from module import func это способ точно указать функцию, которую вы хотите импортировать и поместить в глобальную область видимости. А так же это менее вредно для кода нежели » import * «, т.к. тут ясно видно что импортируется в глобальную область видимости, преимущество более простой записи import module заключается в экономии нажатий клавиш.