CodingStyle/Python: различия между версиями
м (2 версии) |
|||
Строка 1: | Строка 1: | ||
=== | === Стандарт оформления исходного кода на Python === | ||
Данный стандарт выработан с учетом опыта разработки нескольких проектов и обязателен к использованию всеми программистами Etersoft, разрабатывающими на языке Python. | |||
За основу взяты Google Coding Style, Qt Coding Style и некоторые другие. | |||
* [http://qt.gitorious.org/qt/pages/QtCodingStyle http://qt.gitorious.org/qt/pages/QtCodingStyle] | |||
* [http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml] | |||
=== Отступы === | |||
В качестве отступов в исходном коде следует использовать символы табуляции, но не пробелы. Ширина табуляции может настраиваться в текстовом редакторе так, как удобно для восприятия разработчику, в отличие от пробелов, количество которых нельзя уменьшить или увеличить в коде, не переписывая его весь регекспами. | |||
В рамках одного файла с исходным кодом (в дальнейшем - модуля) ни в коем случае нельзя использовать разные виды отступа (пробелы и табуляции одновременно), так как интерпретатор воспримет их некорректно. Типы отступа могут различаться в каждом модуле, но делать это крайне не рекомендуется, поскольку такой подход приведет к путанице и проблемам в дальгейшем. | |||
Некоторые сотрудники, (например, sin@) считают более правильным использование пробелов. Поскольку с его мнением трудно не считаться :-), то было принято следующее правило: тип отступов определяет первый коммитер проекта, его руководитель. Остальные следуют его примеру. Кроме этого пункта, остальные правила кодинг-стайла остаются неизменными. | |||
''Настройка величины табуляции для разных редакторов'' | |||
* Vim: для настройки введите "ESC :set ts=6", таким образом символ табуляции визуально будет выглядеть, как 6 пробелов. Для сохранения настройки надо прописать опцию в конфиг: "echo "set ts=6" >> /.vimrc". Для быстрого преобразования кода, содержащего 2, 4, 6 или 8 пробелов к стандартным табам, можно воспользоваться таким мапом клавиш: | |||
:<pre>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></pre> | |||
:Нажатие F2 вызовет меню из нескольких пунктов, где можно выбрать, сколько пробелов конвертировать в табы и наоборот, привести табы к несокльким пробелам. | |||
=== Имена объектов === | |||
* Имена локальных переменных или членов класса должны состоять только из строчных букв, и не содержать сокращений. Несколько слов в названии переменной должны разделятся символом прочерка (_), но не использованием строчной буквы. | |||
:<pre># Неправильно: | |||
bigRedBall = 4 | |||
my_fnct = lambda : None | |||
# Правильно: | |||
big_red_ball = 4 | |||
my_func = lambda : None</pre> | |||
:Допускается использование общепринятых и распространенных и сокращений, таких, как count, func, err, ptr, const, iter и других. Сокращений, типа intern_err_lvl (internal_error_level) следует избегать. | |||
* Следует избегать названий переменных, состоящий из одной буквы, таких, как i, j, x, y, однако допускается использование их для определения однозначно ассоциируемых понятий, таких, как координаты на плоскости. В случае, если вы хотите использовать такую переменную как счетчик внутри цикла, к ее имени следует добавлять постфикс "_count". | |||
:<pre># Неправильно: | |||
x = 0 | |||
while x < 5 : | |||
pass # Некоторый код... | |||
# Правильно: | |||
x_count = 0 | |||
while x_count < 5 : | |||
pass # Некоторый код...</pre> | |||
* При использовании переменной в качестве элемента итерации или для обозначения ее вида следует использовать постфиксы "_list", "_item", "_dict", "_key", "_flag" (для булевых переменных) и некоторые другие. Если переменная представляет собой экземпляр класс, в терминологии библиотеки являющегося типом, то нужно подписывать другие постфиксы, например, для объекта QWidget в Qt имя будет состоять из нескольких слов плюс постфикс "_widget". Типы QList и QStringList будут иметь одинаковый постфикс "_list", поскольку оба могут быть итерируемы. Элемент итерации для этих типов должен состоять из полного названия объекта плюс префикса "_item", например, "servers_list" и "servers_list_item". | |||
:Исключением можно считать элемент, который сам по себе является более сложным типом данных, например, виджетом. Имя такого элемента определяется произвольным образом с учетом остальных правил и не оканчивается суффиксом "_item". | |||
:<pre># Неправильно: | |||
for i in strings_list : | |||
pass | |||
# Правильно: | |||
for strings_list_item in strings_list : | |||
pass</pre> | |||
* Недопускается объявление разных переменных в одну строчку, однако разрешается присваивание одного значения нескольким переменным. | |||
:<pre># Неправильно: | |||
first = 0; last = 5 | |||
begin = 0; end = 5; | |||
# Правильно: | |||
first = begin = 0 | |||
last = end = 5</pre> | |||
:Такой код можно использовать только в том случае, когда переменные логически близки друг к другу и только при объявлении. Счетчики надо объявлять отдельно. | |||
* Глобальные переменные нужно именовать строчными буквами, начиная каждое слово с прописной буквы. Аббревиатуры в именах таких переменных так же следует именовать исходя из этого правила, то есть, большая буква будет только в начале слова. | |||
:<pre># Неправильно: | |||
XMLHandler_Default = None | |||
# Правильно: | |||
DefaultXmlHandler = None</pre> | |||
:Допускается использование прочерка, в случае, если одна часть имени переменной отражает одну логическую составляющую, а друга часть - другую: | |||
:<pre>F1_Key = 1 | |||
F2_Key = 2 | |||
Return_Key = 3</pre> | |||
* В Python отсутствует такая возможность, как объявление макросов в стиле C или констант C++, поэтому, для создания глобальных (на модуль) констант нужно использовать имена, состоящие из прописныз букв, разделенных подчеркиваниями: | |||
:<pre>LIBS_DIR_PATH = "/usr/lib"</pre> | |||
* Имена классов и метаклассов должны состоять из нескольких слов, каждая первая буква каждого слова должна быть прописной. | |||
:<pre># Неправильно: | |||
class foo_bar(object) : | |||
pass | |||
# Правильно: | |||
class FooBar(object) : | |||
pass</pre> | |||
* Имя функции члена-класса или просто функции модуля должно состоять из строчных букв, начинающихся с прописных. Первая буква имени функции должна быть строчной. | |||
:<pre># Неправильно: | |||
def some_function() : | |||
pass | |||
# Правильно: | |||
def someFunction() : | |||
pass</pre> | |||
: | |||
* Исключение: если одна функция/класс вложена в другую (т.е. замыкание), то внутренняя функция/класс считается локальной переменной и именуется в соответствии с правилами для переменных. | |||
* Для переменных-членов класса используйте имена, начинающиеся с "_" и "__". Первое обозначает, что переменная является закрытой, но ее переназначение допускается при наследовании. Второй тип переменных является полностью закрытым и используется только ввнутри класса родителя, не пересекаясь с дочерним классом, переменная в котором может иметь точно такое же имя. | |||
* Не используйте "_" и "__" для имен функций и классов. Группируйте их по признаку доступа визуально и указывайте комментарий "# Public", "# Private", "Handlers" и другие. Подробнее [http://www.network-theory.co.uk/docs/pytut/PrivateVariables.html тут]. | |||
==== Разделители ==== | |||
* Используйте одну пустую строку для логического разделения процедур. | |||
* Используйте две пустых строки для логического разделения закрытых/открытых функций/переменных/классов на модуль или класс. Сначала пишите группу закрытых объектов, затем группу публичных. | |||
* Операторы присвоения, логические операторы и любые другие нужно разделять пробелами. | |||
* Перед символом ":" обозначающим начало блока, нужно ставить один пробел. | |||
:<pre>Неправильно: | |||
def more(x): | |||
return x**2 | |||
f = lambda a: more(a) | |||
Правильно: | |||
def more(x) : | |||
return x ** 2 | |||
func = lambda more(a) : a</pre> | |||
==== Использование скобок ==== | |||
* Группируйте скобками операции независимо от действия приоритета. | |||
:<pre># Неправильно: | |||
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)</pre> | |||
* По обеим сторонам от внутреннего содержимого скобок не нужно ставить пробелы. Исключения составляют lambda-функции, строчные операторы if-else, и заполнение списка. | |||
:<pre>dir_list = [ item for item in os.listdir(".") if item[0] != "." ] | |||
pow = ( lambda x, n : x ** n ) | |||
line = ( "foo" if True else "bar" )</pre> | |||
:Круглые скобки не нужно указывать, если выражение является единственным вложенным аргументом других скобок. Наличие отступов сохраняется. | |||
:<pre>foo( "foo" if True else "bar" ).</pre> | |||
:Используйте пробелы внутри скобок и табуляцию каждой строки, если содержимое занимает несколько строк, для всех операторов, кроме вызовов функций и конструкторов. | |||
* В остальном, ставьте скобки только там, где они действительно нужны. | |||
==== Комментарии ==== | |||
* Комментарии должны начинаться с символа "#", имеющего после себя один пробел. Комментарии больше длиннее 5 строк должны начинаться и заканчиваться специальной последовательностью """ для многострочных комментариев (docstring) Python. | |||
==== Исключения ==== | |||
* Допускаются любые исключения, если ваш код с использованием вышеописанных правил выглядит не очень хорошо или же здравый смысл подсказывает, что правило в данном случае не подходит. Красота кода остается главным критерием этого кодинг-стайла. | |||
=== Ссылки === | |||
* http://wiki.etersoft.ru/CodingStyle | |||
[[ | [[Category:devel]] |
Версия 14:38, 8 февраля 2014
Стандарт оформления исходного кода на Python
Данный стандарт выработан с учетом опыта разработки нескольких проектов и обязателен к использованию всеми программистами Etersoft, разрабатывающими на языке Python.
За основу взяты Google Coding Style, Qt Coding Style и некоторые другие.
- http://qt.gitorious.org/qt/pages/QtCodingStyle
- http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
Отступы
В качестве отступов в исходном коде следует использовать символы табуляции, но не пробелы. Ширина табуляции может настраиваться в текстовом редакторе так, как удобно для восприятия разработчику, в отличие от пробелов, количество которых нельзя уменьшить или увеличить в коде, не переписывая его весь регекспами.
В рамках одного файла с исходным кодом (в дальнейшем - модуля) ни в коем случае нельзя использовать разные виды отступа (пробелы и табуляции одновременно), так как интерпретатор воспримет их некорректно. Типы отступа могут различаться в каждом модуле, но делать это крайне не рекомендуется, поскольку такой подход приведет к путанице и проблемам в дальгейшем.
Некоторые сотрудники, (например, 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.
Исключения
- Допускаются любые исключения, если ваш код с использованием вышеописанных правил выглядит не очень хорошо или же здравый смысл подсказывает, что правило в данном случае не подходит. Красота кода остается главным критерием этого кодинг-стайла.
Ссылки
* http://wiki.etersoft.ru/CodingStyle