Подкласс класса с частными членами - PullRequest
2 голосов
/ 02 октября 2008

Одна из действительно хороших вещей в python - это простота, с которой вы можете называть переменные с тем же именем, что и метод доступа:

self.__value = 1

def value():
    return self.__value

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

Я знаю, что это, кажется, идет вразрез с общей идеей частного и публичного, но обычно класс, который я пытаюсь сделать подклассом, - это мой собственный класс, от которого я очень рад показать членов подклассу, но не экземпляру. этого класса. Есть ли чистый способ обеспечить это различие?

Ответы [ 3 ]

5 голосов
/ 02 октября 2008

Не удобно, без дальнейшего нарушения инкапсуляции. Атрибут двойного подчеркивания именуется путем добавления символа _ClassName к классу, к которому он обращается. Таким образом, если у вас есть класс ContainerThing с атрибутом __value, атрибут фактически сохраняется как '_ContainerThing__value». Изменение имени класса (или рефакторинг, которому присвоен атрибут) будет означать нарушение всех подклассов, пытающихся получить доступ к этому атрибуту.

Именно поэтому использование двойного подчеркивания именования (которое на самом деле не является «частным», просто «неудобным»), является плохой идеей для использования. Просто используйте одиночное начальное подчеркивание. Каждый будет знать, не трогать ваш «приватный» атрибут, и вы все равно сможете получить к нему доступ в подклассах и в других ситуациях, где это чертовски удобно. Упорядочивание имен атрибутов с двойным подчеркиванием полезно только для того, чтобы избежать столкновений имен для атрибутов, которые действительно специфичны для определенного класса, что крайне редко. Он не обеспечивает дополнительной «безопасности», поскольку даже атрибуты с именами доступны тривиально.

Для записи '__value' и 'value' (и '_value') не совпадают. Подчеркивания являются частью имени.

3 голосов
/ 03 октября 2008

"Я знаю, что это идет вразрез с общей идеей частного и публичного" Не совсем "против", просто отличается от C ++ и Java.

Приватный - как реализовано в C ++ и Java, не очень полезная концепция. Иногда помогает выделить детали реализации. Но это слишком злоупотребляет.

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

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

Мы ставим «частное» в кавычки, потому что это просто соглашение между вами и вашими пользователями. Вы пометили вещи с помощью _. Ваши пользователи (и вы сами) должны это соблюдать.

Часто у нас есть имена функций методов с начальным _, указывающим на то, что мы считаем их «частными» и могут быть изменены без предварительного уведомления.

Бесконечные методы получения и установки, которые требуются Java, не так часто используются в Python. Самоанализ Python более гибкий, у вас есть доступ к внутреннему словарю значений атрибутов объекта, и у вас есть первый класс функций , таких как getattr() и setattr().

Кроме того, у вас есть функция property(), которая часто используется для привязки геттеров и сеттеров к одному имени, которое ведет себя как простой атрибут, но на самом деле это четко определенные вызовы функций методов.

1 голос
/ 02 октября 2008

Не знаю, где его процитировать, но следующее утверждение в отношении защиты доступа - это канон Питона: «Мы все здесь взрослые по обоюдному согласию».

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

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

...