Как вы соглашаетесь различать методы объекта, вызываемые извне, и методы объекта, вызываемые подклассом? - PullRequest
1 голос
/ 25 октября 2008

Я знаю большинство входов и выходов подхода Python к закрытым переменным / members / functions /...

Однако я не могу решить, как различать методы для внешнего использования или для использования подклассов.

Рассмотрим следующий пример:

class EventMixin(object):
    def subscribe(self, **kwargs):
        '''kwargs should be a dict of event -> callable, to be specialized in the subclass'''

    def event(self, name, *args, **kwargs):
        ...

    def _somePrivateMethod(self):
        ...

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

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

self._EventMixin__somePrivateMethod()

Итак, каковы ваши соглашения, кодирование, документирование или иное?

Ответы [ 3 ]

3 голосов
/ 25 октября 2008
use no underscores for the external API,
one underscore for the subclassable API,
and two underscores for the private/internal API

Это разумный и относительно распространенный способ сделать это, да. Двойное подчеркивание для частного (в отличие от «защищенного» в терминах C ++) на практике встречается довольно редко. Вы никогда не знаете, какое поведение подкласс может захотеть изменить, поэтому предположить, что «защищенный», как правило, хорошая ставка, если нет действительно веской причины, по которой связываться с участником может быть особенно опасно.

However, that would become unwieldy because then the internal API would
need to be invoked as self._EventMixin__somePrivateMethod()

Нет, вы можете просто использовать версию с двойным подчеркиванием, и она будет автоматически удалена. Это некрасиво, но работает.

2 голосов
/ 26 октября 2008

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

2 голосов
/ 25 октября 2008

Я обычно нахожу, что использование двойного __ приносит больше хлопот, чем они того стоят, так как это делает юнит-тестирование очень болезненным. использование одного _ в качестве соглашения для методов / атрибутов, которые не предназначены быть частью открытого интерфейса определенного класса / модуля, - мой предпочтительный подход.

...