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