«Частные» свойства атрибута в PythonPython

Программы на Python
Anonymous
 «Частные» свойства атрибута в Python

Сообщение Anonymous »

Я относительно новичок в Python, поэтому надеюсь, что ничего не пропустил, но вот...
Я пытаюсь написать модуль Python и хотел бы создать класс с атрибутом «private», который можно (или, возможно, «следует») изменять только с помощью одной или нескольких функций внутри модуля. Это сделано для того, чтобы сделать модуль более надежным, поскольку установка этого атрибута вне этих функций может привести к нежелательному поведению. Например, у меня может быть:
  • Класс, который хранит значения x и y для точечной диаграммы, Data
  • Функция для чтения значений x и y из файла и сохранения их в классе, read()
  • Функция для их построения,plot()
В этом случае я бы предпочел, чтобы пользователь не мог сделать что-то вроде этого:

Код: Выделить всё

data = Data()
read("file.csv", data)
data.x = [0, 3, 2, 6, 1]
plot(data)
Я понимаю, что добавление одного подчеркивания к имени указывает пользователю, что атрибут не следует изменять, т. е. переименовывать в _x и добавлять декоратор свойства, чтобы пользователь мог получить доступ к значению, не чувствуя себя виноватым. Однако что, если я захочу добавить еще и свойство установки:

Код: Выделить всё

class Data(object):
_x = []
_y = []
@property
def x(self):
return self._x
@x.setter
def x(self, value):
# Do something with value
self._x = value
Теперь я нахожусь в том же положении, что и раньше — пользователь больше не может напрямую получить доступ к атрибуту _x, но он все равно может установить его, используя:

Код: Выделить всё

data.x = [0, 3, 2, 6, 1]
В идеале я бы переименовал определения функций свойств в _x(), но это приводит к путанице относительно того, что на самом деле означает self._x (в зависимости от порядка, в котором они объявлены, это, похоже, приводит либо к рекурсивному вызову установщика, либо к тому, что установщик игнорируется в пользу атрибута).
Я могу придумать несколько решений of:
  • Добавьте двойное подчеркивание к атрибуту __x, чтобы имя было искажено и не путалось с функцией установки. Насколько я понимаю, это должно быть зарезервировано для атрибутов, которые класс не желает делиться с возможными подклассами, поэтому я не уверен, что это законное использование.
  • Переименуйте атрибут, например _x_stored. Хотя это полностью решает проблему, это затрудняет чтение кода и приводит к проблемам с соглашением об именах — какие атрибуты переименовывать? только те, которые актуальны? только те, у которых есть свойства? только те, которые относятся к этому классу?
Применимы ли какие-либо из приведенных выше решений? А если нет, есть ли лучший способ решить эту проблему?
Несколько моментов, поднятых в комментариях:
  • Я хочу сохранить дополнительную логику, которую дает мне свойство setter - раздел # Do Something with value в приведенном выше примере - поэтому внутренняя установка атрибута через прямой доступ к self._x не решает проблему.
  • Удаление свойства setter и создание отдельной функции _set_x() решает проблему, но это не очень аккуратное решение, поскольку оно позволяет устанавливать _x двумя разными способами — либо путем вызова этой функции, либо через прямой доступ к self._x. Тогда мне пришлось бы отслеживать, какие атрибуты должны быть установлены их собственной (не свойственной) функцией установки, а какие должны быть изменены посредством прямого доступа. Я, вероятно, предпочел бы использовать одно из решений, которые я предложил выше, потому что, хотя они и нарушают соглашения об именах внутри класса, они, по крайней мере, единообразны в их использовании вне класса, т. е. все они используют синтаксический сахар свойств. Если нет способа сделать это более аккуратно, то, думаю, мне просто нужно выбрать тот, который вызывает наименьшие нарушения.


Подробнее здесь: https://stackoverflow.com/questions/234 ... -in-python

Вернуться в «Python»