CodingStyle/Python

Материал из Etersoft wiki
Перейти к навигацииПерейти к поиску

Стандарт оформления исходного кода на Python

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

За основу взяты Google Coding Style, Qt Coding Style и некоторые другие.


Отступы

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

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

Некоторые сотрудники, (например, sin@) считают более правильным использование пробелов. Поскольку с его мнением трудно не считаться :-), то было принято следующее правило: тип отступов определяет первый коммитер проекта, его руководитель. Остальные следуют его примеру. Кроме этого пункта, остальные правила кодинг-стайла остаются неизменными.


Настройка величины табуляции для разных редакторов

  • Vim: для настройки введите "ESC :set ts=6", таким образом символ табуляции визуально будет выглядеть, как 6 пробелов. Для сохранения настройки надо прописать опцию в конфиг: "echo "set ts=6" >> /.vimrc". Для быстрого преобразования кода, содержащего 2, 4, 6 или 8 пробелов к стандартным табам, можно воспользоваться таким мапом клавиш:
set wildmenu
 set wcm=<Tab>
 menu SpacesRefactoring.[2\ Spaces\ to\ Tab] :%s#^\( \{2}\)\+#\=repeat("\t", len(submatch(0))/2)#g<Cr>
 menu SpacesRefactoring.[4\ Spaces\ to\ Tab] :%s#^\( \{4}\)\+#\=repeat("\t", len(submatch(0))/4)#g<Cr>
 menu SpacesRefactoring.[6\ Spaces\ to\ Tab] :%s#^\( \{6}\)\+#\=repeat("\t", len(submatch(0))/6)#g<Cr>
 menu SpacesRefactoring.[8\ Spaces\ to\ Tab] :%s#^\( \{8}\)\+#\=repeat("\t", len(submatch(0))/8)#g<Cr>
 menu SpacesRefactoring.[Tab\ to\ 2\ Spaces] :%s#^\(\t\+\)#\=repeat(" ", len(submatch(0))*2)#g<Cr>
 menu SpacesRefactoring.[Tab\ to\ 4\ Spaces] :%s#^\(\t\+\)#\=repeat(" ", len(submatch(0))*4)#g<Cr>
 menu SpacesRefactoring.[Tab\ to\ 6\ Spaces] :%s#^\(\t\+\)#\=repeat(" ", len(submatch(0))*6)#g<Cr>
 menu SpacesRefactoring.[Tab\ to\ 8\ Spaces] :%s#^\(\t\+\)#\=repeat(" ", len(submatch(0))*8)#g<Cr>

nmap <F2> :emenu SpacesRefactoring.<Tab>

Нажатие F2 вызовет меню из нескольких пунктов, где можно выбрать, сколько пробелов конвертировать в табы и наоборот, привести табы к несокльким пробелам.


Имена объектов

  • Имена локальных переменных или членов класса должны состоять только из строчных букв, и не содержать сокращений. Несколько слов в названии переменной должны разделятся символом прочерка (_), но не использованием строчной буквы.
# Неправильно:
 bigRedBall = 4
 my_fnct = lambda : None
 # Правильно:
 big_red_ball = 4

my_func = lambda : None

Допускается использование общепринятых и распространенных и сокращений, таких, как count, func, err, ptr, const, iter и других. Сокращений, типа intern_err_lvl (internal_error_level) следует избегать.
  • Следует избегать названий переменных, состоящий из одной буквы, таких, как i, j, x, y, однако допускается использование их для определения однозначно ассоциируемых понятий, таких, как координаты на плоскости. В случае, если вы хотите использовать такую переменную как счетчик внутри цикла, к ее имени следует добавлять постфикс "_count".
# Неправильно:
 x = 0
 while x < 5 :
       pass # Некоторый код...
 # Правильно:
 x_count = 0
 while x_count < 5 :

pass # Некоторый код...

  • При использовании переменной в качестве элемента итерации или для обозначения ее вида следует использовать постфиксы "_list", "_item", "_dict", "_key", "_flag" (для булевых переменных) и некоторые другие. Если переменная представляет собой экземпляр класс, в терминологии библиотеки являющегося типом, то нужно подписывать другие постфиксы, например, для объекта QWidget в Qt имя будет состоять из нескольких слов плюс постфикс "_widget". Типы QList и QStringList будут иметь одинаковый постфикс "_list", поскольку оба могут быть итерируемы. Элемент итерации для этих типов должен состоять из полного названия объекта плюс префикса "_item", например, "servers_list" и "servers_list_item".
Исключением можно считать элемент, который сам по себе является более сложным типом данных, например, виджетом. Имя такого элемента определяется произвольным образом с учетом остальных правил и не оканчивается суффиксом "_item".
# Неправильно:

for i in strings_list : pass # Правильно: for strings_list_item in strings_list : pass

  • Недопускается объявление разных переменных в одну строчку, однако разрешается присваивание одного значения нескольким переменным.
# Неправильно:
 first = 0; last = 5
 begin = 0; end = 5;
 # Правильно:
 first = begin = 0

last = end = 5

Такой код можно использовать только в том случае, когда переменные логически близки друг к другу и только при объявлении. Счетчики надо объявлять отдельно.
  • Глобальные переменные нужно именовать строчными буквами, начиная каждое слово с прописной буквы. Аббревиатуры в именах таких переменных так же следует именовать исходя из этого правила, то есть, большая буква будет только в начале слова.
# Неправильно:
 XMLHandler_Default = None
 # Правильно:

DefaultXmlHandler = None

Допускается использование прочерка, в случае, если одна часть имени переменной отражает одну логическую составляющую, а друга часть - другую:
F1_Key = 1

F2_Key = 2 Return_Key = 3

  • В Python отсутствует такая возможность, как объявление макросов в стиле C или констант C++, поэтому, для создания глобальных (на модуль) констант нужно использовать имена, состоящие из прописныз букв, разделенных подчеркиваниями:
LIBS_DIR_PATH = "/usr/lib"
  • Имена классов и метаклассов должны состоять из нескольких слов, каждая первая буква каждого слова должна быть прописной.
# Неправильно:
 class foo_bar(object) :
       pass
 # Правильно:
 class FooBar(object) :

pass

  • Имя функции члена-класса или просто функции модуля должно состоять из строчных букв, начинающихся с прописных. Первая буква имени функции должна быть строчной.
# Неправильно:
 def some_function() :
       pass
 # Правильно:
 def someFunction() :

pass

  • Исключение: если одна функция/класс вложена в другую (т.е. замыкание), то внутренняя функция/класс считается локальной переменной и именуется в соответствии с правилами для переменных.
  • Для переменных-членов класса используйте имена, начинающиеся с "_" и "__". Первое обозначает, что переменная является закрытой, но ее переназначение допускается при наследовании. Второй тип переменных является полностью закрытым и используется только ввнутри класса родителя, не пересекаясь с дочерним классом, переменная в котором может иметь точно такое же имя.
  • Не используйте "_" и "__" для имен функций и классов. Группируйте их по признаку доступа визуально и указывайте комментарий "# Public", "# Private", "Handlers" и другие. Подробнее тут.


Разделители

  • Используйте одну пустую строку для логического разделения процедур.
  • Используйте две пустых строки для логического разделения закрытых/открытых функций/переменных/классов на модуль или класс. Сначала пишите группу закрытых объектов, затем группу публичных.
  • Операторы присвоения, логические операторы и любые другие нужно разделять пробелами.
  • Перед символом ":" обозначающим начало блока, нужно ставить один пробел.
Неправильно:
 def more(x):
       return x**2
 f = lambda a: more(a)
 Правильно:
 def more(x) :
       return x ** 2

func = lambda more(a) : a


Использование скобок

  • Группируйте скобками операции независимо от действия приоритета.
# Неправильно:
 if a or b and c :
       pass
 # Правильно:
 if a or (b and c) :
       pass
 # Неправильно:
 x = a or b and c
 # Правильно:

x_flag = a or (b and c)

  • По обеим сторонам от внутреннего содержимого скобок не нужно ставить пробелы. Исключения составляют lambda-функции, строчные операторы if-else, и заполнение списка.
dir_list = [ item for item in os.listdir(".") if item[0] != "." ]
 pow = ( lambda x, n : x ** n )

line = ( "foo" if True else "bar" )

Круглые скобки не нужно указывать, если выражение является единственным вложенным аргументом других скобок. Наличие отступов сохраняется.
foo( "foo" if True else "bar" ).
Используйте пробелы внутри скобок и табуляцию каждой строки, если содержимое занимает несколько строк, для всех операторов, кроме вызовов функций и конструкторов.
  • В остальном, ставьте скобки только там, где они действительно нужны.


Комментарии

  • Комментарии должны начинаться с символа "#", имеющего после себя один пробел. Комментарии больше длиннее 5 строк должны начинаться и заканчиваться специальной последовательностью """ для многострочных комментариев (docstring) Python.


Исключения

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

Ссылки