Я пытаюсь написать модуль Python и хотел бы создать класс с атрибутом «private», который можно (или, возможно, «следует») изменять только с помощью одной или нескольких функций внутри модуля. Это сделано для того, чтобы сделать модуль более надежным, поскольку установка этого атрибута вне этих функций может привести к нежелательному поведению. Например, у меня может быть:
- Класс, который хранит значения x и y для точечной диаграммы, Data
- Функция для чтения значений x и y из файла и сохранения их в классе, read()
- Функция для их построения,plot()
Код: Выделить всё
data = Data()
read("file.csv", data)
data.x = [0, 3, 2, 6, 1]
plot(data)
Код: Выделить всё
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
Код: Выделить всё
data.x = [0, 3, 2, 6, 1]
Я могу придумать несколько решений of:
- Добавьте двойное подчеркивание к атрибуту __x, чтобы имя было искажено и не путалось с функцией установки. Насколько я понимаю, это должно быть зарезервировано для атрибутов, которые класс не желает делиться с возможными подклассами, поэтому я не уверен, что это законное использование.
- Переименуйте атрибут, например _x_stored. Хотя это полностью решает проблему, это затрудняет чтение кода и приводит к проблемам с соглашением об именах — какие атрибуты переименовывать? только те, которые актуальны? только те, у которых есть свойства? только те, которые относятся к этому классу?
Несколько моментов, поднятых в комментариях:
- Я хочу сохранить дополнительную логику, которую дает мне свойство setter - раздел # Do Something with value в приведенном выше примере - поэтому внутренняя установка атрибута через прямой доступ к self._x не решает проблему.
- Удаление свойства setter и создание отдельной функции _set_x() решает проблему, но это не очень аккуратное решение, поскольку оно позволяет устанавливать _x двумя разными способами — либо путем вызова этой функции, либо через прямой доступ к self._x. Тогда мне пришлось бы отслеживать, какие атрибуты должны быть установлены их собственной (не свойственной) функцией установки, а какие должны быть изменены посредством прямого доступа. Я, вероятно, предпочел бы использовать одно из решений, которые я предложил выше, потому что, хотя они и нарушают соглашения об именах внутри класса, они, по крайней мере, единообразны в их использовании вне класса, т. е. все они используют синтаксический сахар свойств. Если нет способа сделать это более аккуратно, то, думаю, мне просто нужно выбрать тот, который вызывает наименьшие нарушения.
Подробнее здесь: https://stackoverflow.com/questions/234 ... -in-python