Этот вопрос основывается на этом предыдущем вопросе, а также этот, но затрагивает более тонкую точку, в частности, что считается "внутренним классом"?
Вот моя ситуация. Я создаю библиотеку Python для управления файлами MS Office, в которых многие из классов не предназначены для создания извне, но многие из их методов являются важными частями API. Например:
class _Slide(object):
def add_shape(self):
...
_Slide
не должен быть создан извне, поскольку конечным пользователем библиотеки вы получаете новый слайд, вызывая Presentation.add_slide()
. Однако, как только у вас есть слайд, вы обязательно захотите позвонить add_shape()
. Таким образом, этот метод является частью API, но конструктор - нет. Эта ситуация возникает десятки раз в библиотеке, потому что только класс Presentation имеет внешний конструктор /API.
PEP8 является двусмысленным в этой точке, ссылаясь на "внутренние классы", не уточняя, что считается внутренним классом. В этом случае, я полагаю, можно сказать, что класс "частично внутренне".
Проблема состоит в том, что у меня есть только две записи для различения по крайней мере трех разных ситуаций:
- Конструктор и методы "public/API" класса доступны для использования.
- Конструктор не должен использоваться, но методы "public/API" этого класса.
- Класс действительно является внутренним, не имеет публичного API, и я оставляю за собой право изменять или удалять его в будущей версии.
Я отмечаю, что с точки зрения коммуникации существует конфликт между четким выражением внешнего API (аудитория конечного пользователя библиотеки) и внутреннего API (аудитория разработчика). Для конечного пользователя вызов _Slide()
является verboten/at-own-risk. Однако он является счастливым членом внутреннего API и отличается от _random_helper_method()
, который должен вызываться только из _Slide()
.
У вас есть точка зрения на этот вопрос, который может мне помочь? Является ли конвенция диктуем, что я использую свои боеприпасы "одного лидера-подчёркивания" в именах классов, чтобы бороться за ясность в API конечных пользователей, или я могу чувствовать себя хорошо о том, чтобы зарезервировать его для общения со мной и другими разработчиками о том, когда API класса действительно закрытый и не используемый, например, объектами вне модуля, в котором он живет, поскольку это может быть изменена деталь реализации.
ОБНОВЛЕНИЕ:. После нескольких лет дальнейшего размышления я согласился с соглашением об использовании главного подчеркивания при назначении классов имен, которые не предназначены для доступа к классу вне их модуля (файл). Такой доступ обычно заключается в создании экземпляра объекта этого класса или для доступа к методу класса и т.д.
Это предоставляет пользователям модуль (часто сам, конечно): базовый индикатор: "Если в заявлении импорта появляется имя класса с ведущим подчеркиванием, вы делаете что-то неправильно".
Обратите внимание, что это доступ к классу. Доступ к объекту этого класса (типа) вне модуля, возможно, предоставлен factory или что-то еще, отлично и, возможно, ожидается. Я думаю, что это неспособность отличить классы от созданных из них объектов, что привело к моей первоначальной путанице.
Это соглашение также имеет побочное преимущество, не включающее эти классы при создании инструкции from module import *
. Хотя я никогда не использую их в своем собственном коде и не рекомендую их избегать, это соответствует поведению, потому что эти идентификаторы классов не предназначены для частичного интерфейса модуля.
Это моя личная "лучшая практика" после нескольких лет испытаний, а не, конечно, "правильный" путь. Ваш пробег может отличаться.