Записки программиста, обо всем и ни о чем. Но, наверное, больше профессионального.

2014-09-16

PEP 8, Naming Conventions

Изучаем PEP 8 по частям. Часть 7, Naming Conventions. TL;DR
Тут говорится о том, что:

В стандартной библиотеке Python немного напортачили с именами, местами используются разные способы именований. Видимо, авторы никогда не наведут здесь полный порядок – тем не менее, излагаем текущие рекомендации стандартов по записи имен. Новые модули и пакеты надо писать по этим стандартам, но если существующая библиотека придерживается другого стиля, не нарушайте его, внутренняя согласованность важнее.

Самый важный принцип: имена видимые пользователю как общедоступные (открытые) интерфейсы, должны отражать использование вместо реализации. Ну, типа если метод пишет в файл текущую температуру воздуха, то этот метод надо назвать «запись_текущей_температуры» а не «выдрать_температуру_с_метеосайта».

Описание стилей именования.

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

Наболее употребимые стили:
* b (однобуквенные, нижний регистр)
* B (однобуквенные, верхний регистр)
* lowercase (нижний регистр, слово)
* lower_case_with_underscores (нижний регистр, слова через подчерк ненавижутакиеписать)
* UPPERCASE (верхний регистр, слово)
* UPPER_CASE_WITH_UNDERSCORES (верхний регистр, слова через подчерк)
* CapitalizedWords (CapWords, CamelCase – слова отбиваемые по первой букве в верхнем регистре). При использовании этого стиля, аббревиатуры пишите полностью в верхнем регистре. Пример: HTTPServerError.
* mixedCase (мой любимый почти как CamelCase, только первая буква в нижнем регистре).
* Capitalized_Words_With_Underscores (отвратительно!)

Есть еще стиль, когда используется общий префикс для группирования имен в рамках некоей темы. Такое в Python встречается не часто, но для полноты картины мы это упомянули. К примеру, функция os.stat() возвращает кортеж, где элементы традиционно называются как-то так: st_mode, st_size, st_mtime, … (Это было сделано для выделения того факта, что есть сильная связь между этими элементами и структурой из вызова POSIX).
Библиотека X11 использует имена начинающиеся с X для всех публичных функций. В Python такой стиль в целом считается ненужным, ибо имена атрибутов и методов предваряются именем объекта, имена функций предваряются именем модуля.

В дополнение есть еще формы с начальным или завершающим подчерком. Они могут быть скомбинированы с любым стилем.
* _single_leading_underscore: индикатор «внутреннего использования», но слабый. К примеру, «from M import *» не будет импортировать такие имена. Это важный пункт, ниже будет масса текста на эту тему.
* single_trailing_underscore_: используется для избегания конфликтов с ключевыми словами Python. Например
Tkinter.Toplevel(master, class_='ClassName')
* __double_leading_uderscore: при именовании атрибута класса вызывает эффект name mangling, что приводит к тому, что внутри класса FooBar атрибут __boo становится _FooBar_boo.
* __double_leading_and_trailing_underscore__: «волшебные» объекты или атрибуты, что живут в пространствах имен, контролируемых пользователем. К примеру, __init__, __import__ или __file__ Никогда не создавайте таких имен, только используйте их, как описано в документации.

Указания по использованию стилей именования.

Избегайте имен: из одной буквы ('l', 'O', 'I') - 'l' (lowercase letter el), 'O' (uppercase letter oh), or 'I' (uppercase letter eye). В некоторых шрифтах отличить эти буквы от других ('1', '0') почти невозможно. Если очень хочется использовать 'l', пишите 'L'.

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

Поскольку имена модулей суть имена файлов, а некоторые файловые системы не различают верхний/нижний регистры и рубят длинные имена, важно, чтобы имена модулей были достаточно короткими. Иначе в старых операционках можно поиметь проблем.

Когда модуль, написанный на C/C++ имеет вспомогательный модуль на Python, предоставляющий более высокоуровневый интерфейс, модуль на C/C++ именуется с добавлением подчерка впереди (например _socket).

Имена классов.
Классы следует именовать используя CapWords стиль.
Можно использовать способ именования функций, если интерфейс документирован и используется в основном как вызываемый (callable).
Отметим, что есть отдельное соглашение для встроенных (builtin, относится скорее к ядру Python) имен: большинство встроенных имен это одиночные слова (или два слова используемые как одно), при этом CapWords используется только для имен исключений (exceptions) и встроенных констант.

Имена исключений.
Поскольку исключения это классы, применимы правила именования классов. Однако, следует использовать суффикс «Error» в именах исключений (если они действительно отражают ошибки).

Имена глобальных переменных.
Будем надеяться, что эти переменные предназначены для использования только внутри модуля. Правила именования такие же, как и для функций. Модули, предназначенные для использования в стиле «from M import *», должны использовать механизм «__all__» для предотвращения экспорта глобальных переменных. Или использовать старый способ с подчеркиванием в качестве префикса имени, что можно трактовать как индикацию таких переменных как «не публичные переменные модуля».

Имена функций надо писать в нижнем регистре, разделяя слова подчерками при необходимости улучшить читабельность. mixedCase допустим только в тех случаях, если такой стиль уже используется (например в threading.py), для сохранения обратной совместимости.

Аргументы функций и методов.
Всегда используйте «self» в качестве первого аргумента в методах инстанса.
Всегда используйте «cls» в качестве первого аргумента метода класса.
Если имена аргументов пересекаются с зарезервированными ключевыми словами, обычно лучше добавить один подчерк в конце имени, нежели использовать аббревиатуры или портить слово выбрасывая/заменяя буквы. В смысле, class_ лучше, чем clss. Возможно, лучше избегать таких коллизий используя синонимы.

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

Чтобы обойти проблему одинаковых имен в подклассах, используйте два начальных подчерка для запуска правил искажения (mangling) имен в Python.
Такие имена Python заменяет на составные: _имя класса__имя метода. Если класс Foo содержит атрибут __a, его нельзя потрогать за Foo.__a, хотя настойчивые могут попробовать Foo._Foo__a. В целом, двойной начальный подчерк следует использовать только для избегания конфликта имен в классах, предназначенных быть подклассами.
Заметим: есть некоторые противоречия в использовании имен с двумя подчерками __names.

Константы обычно определены на уровне модуля и записаны в верхнем регистре, подчерки разделяют слова. Примеры: MAX_OVERFLOW, TOTAL.

Проектируя для наследования.
Всегда определяйтесь, методы класса и переменные инстанса (в общем – атрибуты) будут публичными или закрытыми. Если сомневаетесь, выбирайте закрытые. Легче их потом сделать открытыми, чем закрывать публичные атрибуты.
Публичные атрибуты, это те, что будут использованы посторонними клиентами класса, что подтверждается вашим обязательством избегать изменений приводящих к обратной несовместимости. Закрытые атрибуты, это те, что не предназначены для использования третьими лицами. Вы не даете никаких гарантий, что закрытые атрибуты не изменятся или даже будут удалены.
Мы здесь не используем термин «private», поскольку нет реально приватных атрибутов в Python.
Другая категория атрибутов, называемая в других языках «protected», это та, что является «API подкласса». Некоторые классы проектируются для того, чтобы от них наследовали, либо для расширения, либо для изменения аспектов поведения класса. Когда проектируете такой класс, позаботьтесь явным образом решить, какие атрибуты открыты, какие часть API подкласса и какие будут использованы только в базовом классе.

Учитывая вышеизложенное, вот руководства:
* Открытые (public) атрибуты не должны начинаться с подчеркивания.
* Если имена открытых атрибутов совпадают с зарезервированными ключевыми словами, добавьте к хвосту слова подчерк. Лучше так, чем аббревиатура или испорченное написание слова. Тем не менее, «cls» это предпочтительное название переменной или аргумента, про который известно, что это класс, особенно, если это первый аргумент в методе класса.
* Для простых атрибутов, представляющих данные, лучше открывать только имя атрибута, без сложных методов доступа/изменения. Не забывайте, Python дает легкий путь к будущим усовершенствованиям вашего кода, если вы обнаружите, что простой атрибут нуждается в более сложном поведении. В этом случае используйте свойства (properties) для упрятывания функциональности позади простого синтаксиса доступа к простому атрибуту.
Заметки:
свойства доступны только в классах нового стиля. Постарайтесь такое поведение делать без сайд-эффектов. Не используйте свойства для вычислительно дорогих операций; нотация говорит пользователю, что доступ относительно дешев, не расстраивайте его.
* Если предполагается, что у класса будут подклассы (наследники) и есть атрибуты, которые вы не хотите давать наследникам в пользование, подумайте об использовании двойного подчеркивания вначале имени такого атрибута. Это вызовет name mangling, что приведет к появлению составного (из имени класса и имени атрибута) имени. Это помогает избежать коллизий имен в подклассах.
Заметки:
если подкласс использует, кроме совпадающего имени атрибута, совпадающее имя класса, name mangling не поможет. Name mungling может сделать отладку менее удобной, как и использование __getattr__(). Однако, алгоритм хорошо документирован и легко выполняется вручную. Не всем нравится name mangling. Постарайтесь не злоупотреблять.

Внешние и внутренние интерфейсы.
Любые гарантии обратной совместимости могут рассматриваться только для внешних (public) интерфейсов. Посему важно, чтобы пользователи могли четко различать внешние и внутренние интерфейсы (и избегать пользоваться внутренними).
Документированные интерфейсы рассматриваются как внешние, пока документация явно не объявит их иными (вспомогательными, внутренними), исключая из гарантий обратной совместимости. Все недокументированные интерфейсы рассматриваются как внутренние.
Для лучшей поддержки интроспекции, в модулях следует явно объявлять имена их внешних интерфейсов используя атрибут __all__. Установка __all__ в пустой список показывает, что у модуля нет внешнего API.
Даже правильно записав __all__, внутренние интерфейсы (пакеты, модули, классы, функции, атрибуты, пр.) следует именовать с добавлением впереди подчерка.
Интерфейс рассматривается как внутренний, если он находится внутри внутреннего интерфейса.
Импортированные имена следует всегда рассматривать как детали реализации. Другие модули не должны полагаться на непрямой доступ к таким именам, пока они явно не документированы как часть API их модуля, как os.path или модуль __init__ открывающий функциональность из подмодулей пакета.


Слов много, но суть очень простая: отделяйте мух от котлет закрытые интерфейсы от открытых, используя подчерк перед именами для закрытых и записывая открытые в переменную __all__ модуля. Используйте стиль lowercase_name для именования всего, кроме пакетов (подчерк в имени пакета не нужно) и классов. Классы именуйте в стиле CamelCase. При желании использовать зарезервированное слово в качестве имени, добавьте в конце подчерк. Константы записывайте в стиле UPPER_CASE. Имейте в виду, что существует name mangling.

И будет вам щасте.




original post http://vasnake.blogspot.com/2014/09/pep-8-naming-conventions.html

Комментариев нет:

Отправить комментарий

Архив блога

Ярлыки

linux (241) python (191) citation (185) web-develop (170) gov.ru (157) video (123) бытовуха (112) sysadm (100) GIS (97) Zope(Plone) (88) Book (81) programming (81) бурчалки (81) грабли (77) development (73) Fun (72) windsurfing (72) Microsoft (64) hiload (62) opensource (58) internet provider (57) security (57) опыт (55) movie (52) Wisdom (51) ML (47) language (45) hardware (44) JS (41) curse (40) driving (40) money (40) DBMS (38) bigdata (38) ArcGIS (34) history (31) PDA (30) howto (30) holyday (29) Google (27) Oracle (27) virtbox (27) health (26) vacation (24) AI (23) Autodesk (23) SQL (23) Java (22) humor (22) knowledge (22) translate (20) CSS (19) cheatsheet (19) hack (19) tourism (19) Apache (16) Manager (15) web-browser (15) Никонов (15) happiness (14) music (14) todo (14) PHP (13) course (13) functional programming (13) weapon (13) HTTP. Apache (12) SSH (12) frameworks (12) hero (12) im (12) settings (12) HTML (11) SciTE (11) crypto (11) game (11) map (11) scala (11) HTTPD (9) ODF (9) купи/продай (9) benchmark (8) documentation (8) 3D (7) CS (7) DNS (7) NoSQL (7) Photo (7) cloud (7) django (7) gun (7) matroska (7) telephony (7) Microsoft Office (6) VCS (6) bluetooth (6) pidgin (6) proxy (6) Donald Knuth (5) ETL (5) NVIDIA (5) REST (5) bash (5) flash (5) keyboard (5) price (5) samba (5) CGI (4) LISP (4) RoR (4) cache (4) display (4) holywar (4) nginx (4) pistol (4) xml (4) Лебедев (4) IDE (3) IE8 (3) J2EE (3) NTFS (3) RDP (3) USA (3) holiday (3) mount (3) spark (3) Гоблин (3) кухня (3) урюк (3) AMQP (2) ERP (2) IE7 (2) NAS (2) Naudoc (2) PDF (2) address (2) air (2) british (2) coffee (2) font (2) ftp (2) messaging (2) notify (2) sharepoint (2) ssl/tls (2) stardict (2) tests (2) tunnel (2) udev (2) APT (1) CRUD (1) Canyonlands (1) Cyprus (1) DVDShrink (1) Jabber (1) K9Copy (1) Matlab (1) Palanga (1) Portugal (1) VBA (1) WD My Book (1) autoit (1) bike (1) cannabis (1) chat (1) concurrent (1) dbf (1) ext4 (1) idioten (1) krusader (1) license (1) mindmap (1) pneumatic weapon (1) quiz (1) regexp (1) robot (1) science (1) serialization (1) tie (1) vim (1) Науру (1) крысы (1) налоги (1) пианино (1)

Google+ Followers