Сообщить об ошибке.

Соглашения об именах в Python

Как называть переменные и объекты в коде

Соглашения об именах библиотеки Python немного беспорядочные, поэтому мы никогда не получим полное согласование. Тем не менее, вот рекомендуемые в настоящее время стандарты именования. Новые модули и пакеты (включая сторонние фреймворки) должны быть написаны в этих стандартах, но там, где существующая библиотека имеет другой стиль, внутренняя согласованность предпочтительнее.

Главный принцип: Имена, которые видны пользователю как открытые части API, должны соответствовать соглашениям, которые отражают использование, а не реализацию.

Описание стилей именования в языках программирования:

Есть много разных стилей именования. Это помогает понять, какой стиль именования используется независимо от того, для чего он используется.

Следующие стили именования обычно различаются:

  • b (одна строчная буква)
  • B (одна заглавная буква)
  • lowercase (в нижнем регистре)
  • lower_case_with_underscores (нижний регистр с подчеркиванием)
  • UPPERCASE (в верхнем регистре)
  • UPPER_CASE_WITH_UNDERSCORES (верхний регистр с подчеркиванием)
  • CapitalizedWords (или CapWords, или CamelCase - так названы из-за неровного вида его букв). Это также иногда называют StudlyCaps.
    Примечание. При использовании аббревиатур в CapWords используйте заглавные буквы заглавных букв. Таким образом, HTTPServerError лучше, чем HttpServerError.
  • mixedCase (отличается от CapitalizedWords начальным символом в нижнем регистре!)
  • 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_underscore: изменяет имя атрибута класса (внутри класса FooBar __boo становится _FooBar__boo).

  • __double_leading_and_trailing_underscore__: "магические" объекты или атрибуты, которые находятся в управляемых пользователем пространствах имен. Например, __init__ , __import__ или __file__ . Никогда не изобретайте такие имена; используйте их только как задокументировано.

Соглашения об именах в Python.

Имена, которых следует избегать:

Никогда не используйте символы l (строчная буква L), O (заглавная буква o) или I (заглавная буква i) в качестве имен переменных из одного символа.

В некоторых шрифтах эти символы неотличимы от цифр один и ноль. Когда возникает искушение использовать l, используйте L.

Совместимость с ASCII:

Идентификаторы, используемые в стандартной библиотеке должны быть ASCII совместимы, как описано в разделе политики в PEP 3131.

Имена пакетов и модулей:

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

Так как имена модулей отображаются в именах файлов, а некоторые файловые системы являются нечувствительными к регистру символов и обрезают длинные имена, очень важно использовать достаточно короткие имена модулей - это не проблема в Unix, но, возможно, код окажется непереносимым в старые версии Windows, Mac, или DOS.

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

Имена классов:

Имена классов должны обычно использовать соглашение CapWords.

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

Обратите внимание, что для встроенных имен существует отдельное соглашение: большинство встроенных имен представляют собой отдельные слова (или два слова, идущие вместе), причем соглашение CapWords используется только для имен исключений и встроенных констант.

Имена типов переменных:

Имена типов переменных, представленные в PEP 484, должны обычно использовать CapWords, предпочитая короткие имена: T, AnyStr, Num. Рекомендуется добавить суффиксы _co или _contra к переменным, используемым для объявления ковариантного или контравариантного поведения соответственно:

from typing import TypeVar

VT_co = TypeVar('VT_co', covariant=True)
KT_contra = TypeVar('KT_contra', contravariant=True)

Имена исключений:

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

Имена глобальных переменных:

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

Модули, спроектированные для использования с помощью from M import *, должны использовать механизм __all__ для предотвращения экспорта глобальных файлов или использовать более старое соглашение о добавлении префиксов для таких глобальных символов с подчеркиванием (что может потребоваться для указания того, что эти глобальные переменные являются "непубличными модулями").

Имена функций:

Имена функций должны быть строчными, слова должны быть разделены подчеркиванием, чтобы улучшить читаемость.

Имена переменных следуют тому же соглашению, что и имена функций.

mixedCase допускается только в тех случаях, когда уже преобладает такой стиль, для сохранения обратной совместимости.

Аргументы функций и методов:

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

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

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

Имена методов и переменных экземпляра класса:

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

Используйте одно начальное подчеркивание только для закрытых методов и переменных экземпляра.

Чтобы избежать конфликта имен с подклассами, используйте два ведущих подчеркивания для вызова правил искажения имен в Python.

Python связывает эти имена с именем класса: если класс Foo имеет атрибут с именем __a , Foo не сможет получить к нему доступ как Foo.__a . (Настойчивый пользователь все еще может получить доступ, вызвав Foo._Foo__a.) Как правило, двойные начальные подчеркивания должны использоваться только во избежание конфликтов имен с атрибутами в классах, предназначенных для подклассов.

Примечание: есть некоторые противоречия по поводу использования __names (см. Ниже).

Константы:

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

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

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

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

Мы не используем термин "приватный", поскольку ни один атрибут не является таковым в Python.

Другая категория атрибутов - это те, которые являются частью "подкласса API" (часто называемого "защищенным (protected)" в других языках). Некоторые классы проектируются так, чтобы от них наследовали другие классы, которые расширяют или модифицируют поведение базового класса. Когда вы проектируете такой класс, решите и явно укажите, какие атрибуты являются публичными, какие принадлежат API подклассов, а какие используются только базовым классом.

Имея это в виду, вот данные руководящие принципы:

  • Публичные атрибуты не должны иметь начальных подчеркиваний.

  • Если имя вашего общедоступного атрибута вступает в противоречие с зарезервированным ключевым словом, добавьте к его имени один завершающий символ подчеркивания. Это предпочтительнее аббревиатуры или искаженного написания. (Однако, несмотря на это правило, cls является предпочтительным написанием для любой переменной или аргумента, который, как известно, является классом, особенно первым аргументом для метода класса.)

    Примечание 1: См. Рекомендацию выше имени аргумента для методов класса.

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

    Примечание 1: Свойства properties работают только с классами нового стиля.

    Примечание 2: Старайтесь не допускать побочных эффектов функционального поведения, хотя, такие как кэширование, обычно хороши.

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

  • Если ваш класс предназначен для использования в подклассах (наследование), и у вас есть атрибуты, которые вы не хотите использовать в наследовании, рассмотрите возможность присвоения им имен с двойным нижним подчеркиванием и без завершающего подчеркивания. Это вызывает алгоритм искажения имени Python, где имя класса искажается в имя атрибута. Это помогает избежать конфликтов имен атрибутов, если подклассы непреднамеренно содержат атрибуты с одинаковыми именами.

    Примечание 1: Обратите внимание, что в искаженном имени используется только простое имя класса, поэтому, если подкласс выбирает одно и то же имя класса и имя атрибута, вы все равно можете получить конфликты имен.

    Примечание 2: искажение имен может сделать некоторые применения, такие как отладка и __getattr__() , менее удобными. Однако алгоритм искажения имени хорошо документирован и его легко выполнить вручную.

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

Публичные и внутренние интерфейсы

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

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

Чтобы лучше поддерживать интроспекцию, модули должны явно объявлять имена в своем публичном API, используя атрибут __all__ . Установка __all__ в пустой список означает, что модуль не имеет публичного API.

Даже при правильной установке __all__ внутренние интерфейсы (пакеты, модули, классы, функции, атрибуты или другие имена) должны по-прежнему иметь префикс с единственным начальным подчеркиванием.

Интерфейс также считается внутренним, если содержащее пространство имен (пакет, модуль или класс) считается внутренним.

Импортированные имена всегда должны рассматриваться как детали реализации. Другие модули не должны полагаться на косвенный доступ к таким импортированным именам, если они не являются явно документированной частью API содержащего модуля, такого как os.path или модуля __init__ пакета, который предоставляет функциональность из подмодулей.