Сделать атрибуты доступными только для чтения, если это необходимо.Не делайте каждый атрибут по умолчанию доступным только для чтения.
Нет ничего плохого в использовании свойств для реализации атрибутов только для чтения.Это одна из причин, почему свойства являются частью Python.С другой стороны, нет ничего особенно правильного в том, чтобы сделать большинство атрибутов доступными только для чтения.Это идет вразрез со стандартной идиомой Python и затрудняет взаимодействие с вашими классами (особенно изнутри вашей собственной базы кода).Имейте в виду, что в Python нет эквивалента ключевому слову C ++ private
.Например, несмотря на то, что x
только для чтения, пользователь ничем не мешает посвятить себя стрельбе в ногу из-за того, что он все равно делает self._x = 19
.
Как правило, достаточно использовать нижнее подчеркивание _name
Соглашение о пометке внутренних и общедоступных атрибутов:
class Foo:
def __init__(self, bar, baz):
self._mine = bar
self.public = baz
Как и предполагалось, атрибуты x
и y
вашего класса Point
являются хорошими кандидатами на атрибуты только для чтения.Однако я бы сказал, что Pythonic более гибко спроектирует ваш класс и сделает расстояние методом:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def distance(self):
return (x**2 + y**2) ** (1/2)
Или, если производительность является проблемой, оставьте distance
как свойство, но пересчитывайте его всякий раз, когда x
или y
изменить:
class Point:
@staticmethod
def _distance(x, y):
return (x**2 + y**2) ** (1/2)
@property
def x(self):
return self._x
@x.setter
def x(self, x):
self._x = x
self._distance = Point._distance(x, self._y)
@property
def y(self):
return self._y
@y.setter
def y(self, y):
self._y = y
self._distance = Point._distance(self._x, y)
distance = property(lambda self: self._distance)
def __init__(self, x, y):
self._x = x
self._y = y
self._distance = Point._distance(x, y)