Оправданы ли в Python методы доступа? - PullRequest
9 голосов
/ 20 июля 2010

Я понимаю, что в большинстве случаев в Python предпочтительнее просто обращаться к атрибутам напрямую, поскольку нет реальной концепции инкапсуляции, как в Java и тому подобном. Однако мне интересно, нет ли каких-либо исключений, особенно с абстрактными классами, которые имеют несопоставимые реализации.

Допустим, я пишу несколько абстрактных классов (потому что я есть) и они представляют вещи, имеющие отношение к системам контроля версий, таким как репозитории и ревизии (потому что они это делают). Нечто подобное SvnRevision, HgRevision и GitRevision очень тесно семантически связаны, и я хочу, чтобы они могли делать то же самое (чтобы я мог иметь код в другом месте, который действует на любой тип объекта Repository и не зависит от подкласс), поэтому я хочу, чтобы они наследовали от абстрактного класса. Однако их реализации значительно различаются.

Пока что реализованные подклассы имеют много общих имен атрибутов, и во многих кодах вне самих классов используется прямой доступ к атрибутам. Например, каждый подкласс Revision имеет атрибут автора, атрибут даты и т. Д. Однако атрибуты нигде не описаны в абстрактном классе. Это кажется мне очень хрупким дизайном.

Если кто-то хочет написать другую реализацию класса Revision, я чувствую, что он должен сделать это, просто взглянув на абстрактный класс. Однако реализация класса, которая удовлетворяет всем абстрактным методам, почти наверняка потерпит неудачу, потому что автор не будет знать, что им нужны атрибуты с именами «author» и «date» и т. Д., Поэтому код, который пытается получить доступ к Revision. Автор выбросит исключение. Вероятно, нетрудно найти источник проблемы, но, тем не менее, раздражает, и это просто похоже на не элегантный дизайн.

Моим решением было написать методы доступа для абстрактных классов (get_id, get_author и т. Д.). Я подумал, что это на самом деле довольно чистое решение, так как оно устраняет произвольные ограничения на то, как атрибуты именуются и хранятся, и просто дает понять, к каким данным объект должен иметь доступ. Любой класс, который реализует все методы абстрактного класса, будет работать ... это правильно.

В любом случае, команда, с которой я работаю, ненавидит это решение (по-видимому, по той причине, что средства доступа не являются пифоническими, с чем я не могу поспорить). Итак ... какая альтернатива? Документация? Или проблема, которую я представляю, не является проблемой?

Примечание: я рассмотрел свойства, но не думаю, что они являются более чистым решением.

Ответы [ 5 ]

8 голосов
/ 20 июля 2010

Примечание: я рассмотрел свойства, но не думаю, что они являются более чистым решением.

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

def _get_id(self):
   return self._id

def _set_id(self, newid):
   self._id = newid

Скорее всего, похоже на то, что у вас есть сейчас.Чтобы успокоить вашу команду, вам просто нужно добавить следующее:

id = property(_get_id, _set_id)

Вы также можете использовать property в качестве декоратора:

@property
def id(self):
    return self._id

@id.setter
def id(self, newid):
    self._id = newid

И сделать это только для чтения,просто пропустите set_id / бит id.setter.

4 голосов
/ 20 июля 2010

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

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

1 голос
/ 20 июля 2010

"они должны быть в состоянии сделать это, просто взглянув на абстрактный класс"

Не знаю, что это должно быть правдой.«Руководство программиста», «как расширить» документ, плюс какое-то обучение кажется мне подходящим.

«автор не будет знать, что ему нужны атрибуты, называемые« автор »и« дата »и так далее".

В этом случае документация не полная.Возможно, абстрактному классу нужна лучшая строка документации.Или «Руководство программиста», или «Как расширить» документ.

Кроме того, не представляется очень сложным (1) документировать эти атрибуты в строке документации и (2) предоставлять значения по умолчанию в__init__ method.

Что плохого в предоставлении дополнительной поддержки программистам?

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

1 голос
/ 20 июля 2010
0 голосов
/ 03 июля 2011

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

Однако реализация класса, которая удовлетворяет всем абстрактным методам, почти наверняка потерпит неудачу, потому чтоавтор не будет знать, что ему нужны атрибуты с именами «author», «date» и т. д., поэтому код, пытающийся получить доступ к Revision.author, выдаст исключение.

Э-энеправильно.(Что сказал С. Лотт, за вычетом личных комментариев).Если это обязательные члены, разве они не упоминаются (если не требуются) в конструкторе и определяются docstring?или, по крайней мере, по мере необходимости, аргументы методов и снова документированные?Как могли пользователи класса , а не знать, что такое обязательные члены?Чтобы быть защитником дьявола, что, если ваш конструктор (-ы) потребует от вас предоставить всех членов, которые потребуются / могут потребоваться, какая проблема это вызывает?Кроме того, вы проверяете параметры при передаче и генерируете информативные исключения?

(Идеологическим аргументом accessor-vs-property является боковая панель. Свойства предпочтительнее, но я не думаю, что это проблема вашего классадизайн.)

...