3. Руководство по оформлению программ на Python

Author: Guido van Rossum
Оригинальная статья на английском: http://www.python.org/doc/essays/styleguide.html Python Style Guide
Перевод выполнен компанией «Калкулэйт».

Общие замечания

Это руководство - о логике программирования. Важно следовать этому руководству в стиле программы.
Ещё более важна логичность всего проекта. Логичность в пределах одного модуля или функции - важнейшее требование. Но важнее всего знать, когда отступить от стиля и логичности. Иногда это руководство просто неприменимо. Если вы затрудняетесь, посмотрите на примеры и решите, что лучше.

Разметка

Отступы

Используйте параметры по умолчанию: 4 пробела на один отступ. Для очень старого кода, в который вы не желаете сильно вмешиваться, можете можете продолжать использовать отступы в 8 символов.

Табуляция или пробелы?

Никогда не смешивайте пробелы с табуляцией. Самый популярный способ отступов в Питоне - использовать только пробелы. Второй самый популярный способ - только табуляторы. Код, в котором отступы пробелами и табуляторами перемешаны, надо перевести к отступам пробелами. Когда вы запускаете Питон с параметром -t, то при использовании смешанных отступов выдаются предупреждения; если задать опцию -tt, то предупреждения станут ошибками. Использование этих опций очень рекомендуется!

Максимальная длина строки

До сих пор существует много устройств, длина строки в которых ограничена 80-ю символами. Поэтому, пожалуйста, установите максимальную длину для всех строк 79 символов.

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

class Rectangle(Blob):
   def __init__(self, width, height,
                color='black', emphasis=None, highlight=0):
       if width == 0 and height == 0 and \
          color == 'red' and emphasis == 'strong' or \
          highlight > 100:
              raise ValueError, "sorry, you lose" 
       if width == 0 and height == 0 and (color == 'red' or
                                          emphasis is None):
           raise ValueError, "I don't think so" 
       Blob.__init__(self, widt, height,
                     color, emphasis, highlight)

Пустые строки

Отделяйте функции верхнего уровня и объявления классов двумя пустыми строками. Определения методов внутри класса отделяются одной пустой строкой. Дополнительно пустые строки можно использовать для отделения групп родственных функций. Пустые строки можно опускать внутри связки из одностроковых определений (набора абстрактных методов).
Если пустые строки используются для отделения методов в классе, то вставляйте также пустую строку между строкой "class..." и определением первого метода.
Используйте пустые строки в функциях для указания логических блоков, но не переусердствуйте.

Пробелы в выражениях и операторах

Я (Pet Peeves) ненавижу пробелы в следующих местах:
  • Сразу после скобок:
    spam( ham[ 1 ], { eggs: 2 } ).
    
    Всегда пишите так:
    spam(ham[1], {eggs: 2}).
    
  • Непосредственно перед двоеточием, точкой с запятой, запятой:
    if x == 4 : print x , y ; x , y = y , x.
    
    Всегда пишите:
    if x == 4: print x, y; x, y = y, x.
    
  • Перед открывающей скобкой при вызове функции:
    spam (1)
    
    Всегда пишите:
    spam(1)
    
  • Перед открывающими скобками индекса или разреза:
    dict ['key'] = list [index].
    
    Всегда пишите:
    dict['key'] = list[index].
    
  • Более чем один пробел вокруг присваивания или другого оператора:
    x             = 1
    y             = 2
    long_variable = 3
    
    Всегда пишите так:
    x = 1
    y = 2
    long_variable = 3
    

Другие рекомендации

ВСЕГДА окружайте эти бинарные операторы одинарными пробелами:
  • присваивание
  • сравнения (==, <, >, !=, <>, <=, >=, in, not in, is, is not),
  • Булевы (and, or, not).

Используйте наилучший по вашему мнению выбор при вставке пробелов вокруг арифметических операторов. Всегда будьте последовательны при вставке пробелов в обоих частях бинарного оператора:

i = i+1
submitted = submitted + 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
c = (a + b) * (a - b)

Не используйте пробелы вокруг знака '=' в случае указания значения по умолчанию:

def complex(real, imag=0.0):
    return magic(r=real, i=imag)

Комментарии

Комментарии, которые противоречат коду, хуже, чем код без комментариев вообще.
Всегда поддерживайте актуальность комментариев, изменяйте их каждый раз при изменениях кода!

Если комментарий - фраза или предложение, его первая буква должна быть заглавной, если только это не идентификатор.

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

Используйте два пробела после точки в конце предложения.

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

Блоковые комментарии

Блоковые комментарии обычно распространяются на код, который следует сразу за ними и располагается на одном с ними уровне отступа. Каждая строка в блоке комментария начинается с # и одного пробела. Параграфы в комментариях отделяются строкой с одним символом #.
Лучше всего отделять блоковые комментарии пустыми строками сверху и снизу. Если это блок комментария, который начинает новый раздел функций, то сверху можно поставить две пустых строки.

Внутристроковые комментарии

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

Внутристроковые комментарии излишни и отвлекают, если их значение и так очевидно:

x = x+1   # Увеличение х на единицу

Но иногда может быть полезно:
x = x+1   # Для компенсации толщины рамки

Строки документации

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

Строки документации должны быть написаны в стиле "Usage" - информации, которая обычно выдается программами на экран при вызове с ключом -h или -help.

Всегда используйте """тройные сдвоенные кавычки""" для выделения строк документации.

Есть два вида строк документации - однострочные и многостроковые.

Одностроковые

def find_root():
    """Решить уравнение и вернуть его корень.""" 
    ...
  • Используйте """тройные сдвоенные кавычки"""
  • закрывающие кавычки на той же строке
  • никаких пустых строк до или после комментария
  • Фраза заканчивается точкой.
  • Пишите в стиле команды, приказа ('''Сделать''' это, '''вернуть''' то-то).
  • Никогда не пишите что-то типа "Функция возвращает..."

Многостроковые

Начинаются одной обобщающей строкой, за которой следует пустая строка и более полное описание.

Рекомендуется перед закрывающими тройными кавычками вставлять пустую строку.
Каждый аргумент лучше начинать с новой строки и отделять от описания двумя тире:

def complex(real=0.0, imag=0.0):
    """Form a complex number.

    Keyword arguments:
    real -- the real part (default 0.0)
    imag -- the imaginary part (default 0.0)

    """ 
    if imag == 0.0 and real == 0.0: return complex_zero
    ...

Поддержка контроля версий

Если вы используете RCS или CVS, то пишите следующим образом:

__version__ = "$Revision: 6104 $" 
# $Source$

Вставляйте это после строк документации перед началом кода, отделяя сверху и снизу пустой строкой.

Именование

Способы именования в библиотеках Питона - это всегда маленький хаос. Здесь никогда не будет полной логичности и порядка. Тем не менее дадим несколько рекомендаций.

Стили именования

Стилей много. Наиболее распространены следующие:
  • x (одна маленькая буква)
  • X (одна большая буква)
  • lowercase - маленькими буквами
  • lower_case_with_underscores - маленькими буквами с подчеркиваниями
  • UPPERCASE - большими буквами
  • UPPER_CASE_WITH_UNDERSCORES - большими буквами с подчеркиваниями
  • CapitalizedWords (or CapWords) - Заглавные буквы слов
  • mixedCase - смешанный
  • Capitalized_Words_With_Underscores - Заглавные буквы слов + подчеркивания (какое убожество!)
В дополнение существуют следующие специальные формы с символами подчеркивания:
  • _single_leading_underscore: внутреннее использование, ("from M import *" не будет импортировать такие имена)
  • single_trailing_underscore_: исп. для предотвращения конфликтов с зарезервированными словани Питона (Tkinter.Toplevel(master, class_="ClassName")).
  • __double_leading_underscore: private-имена класса в Python 1.4.
  • double_leading_and_trailing_underscore: "волшебные" объекты, например init, import или file.

Стили предписаний

Названия модулей

Имена модулей можно писать в стиле "MixedCase" или "lowercase".
Модули, которые экспортируют один класс, обычно называют в стиле MixedCase, а имя модуля совпадает с именем класса (например, стандартный модуль StringIO).
Модули, которые экспортируют множество функций, обычно называют в стиле lowercase.

В случае когда модуль расширения написанный на C или C++ имеет сопровождающий его модуль на Питоне, который представляет собой интерфейс высокого уровня (объектно ориентированный), питоновский модуль называют в виде "ModuleName", а модуль C/C++ - "_modulename".

Class Names

Имена классов обычно используют стиль "CapWords". Классы для внутреннего пользования начинаются с подчеркивания.

Exception Names

Если модуль вызывает одно исключение при любой ошибке, то его обычно называют "error" или "Error". Например встроенные модули расширений используют "error" (os.error), а питоновские модули - "Error" (xdrlib.Error).

Function Names

Обычные функции, которые экспортирует модуль, могут быть в любом стиле "CapWords" или "lowercase" (или "lower_case_with_underscores"). Стиль "CapWords" используется для функций, которые предоставляют наибольшую функциональность. (nstools.WorldOpen()), а "lowercase" - для мелких функций (pathhack.kos_root()).

Global Variable Names

То же, что и для экспортируемых функций.

Method Names

Как для всех функций.

Спасибо!