Свойство Python против метода, когда не требуется доступ к атрибуту?

Я читаю "Программирование на Python для абсолютного новичка", и там есть эта часть кода:

@property
def mood(self):
    unhappiness = self.hunger + self.boredom
    if unhappiness < 5:
        m = "happy"
    elif 5 <= unhappiness <= 10:
        m = "okay"
    elif 11 <= unhappiness <= 15:
        m = "frustrated"
    else:
        m = "mad"
    return m

Все, что он делает, вычисляет на лету и возвращает расчет. Он не предоставляет доступ к частному атрибуту или любому атрибуту класса. Это лучше как свойство, а не метод?

Ответ 1

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

Как таковой, обычно это не вопрос "лучше", а скорее дизайнерское решение с плюсами и минусами, которые зависят от контекста.

В этом случае, независимо от того, что этот объект поддерживает x.hunger, x.boredom и x.mood. Почему бы не x.mood()? Вы могли бы, хотя это постоянно показывает в интерфейсе, что это расчет и не сохраняется.

Если предыдущая версия класса имела "реальный" mood атрибут, а требуемый инвариант объекта означал, что любой внутренний метод, обновляющий boredom или hunger, должен был также тщательно установить mood последовательный, то введение этого свойства было бы отличным рефактором; интерфейс остается прежним, но теперь гарантируется, что инвариант всегда будет удерживаться, а не быть осторожным. Целая область ошибок становится невозможной.

С другой стороны, если mood является дорогостоящим для вычисления или имеет побочные эффекты, то он, вероятно, будет намного лучше, чем обычный метод. Сделать его похожим на доступ к атрибуту означает, что программисты на клиентских кодах, скорее всего, будут рассматривать его как доступ к атрибуту, который является дешевым и неразрушающим; это будет большим источником ошибок или проблем с производительностью.

Ответ 2

Я не думаю, что есть какая-то реальная разница.

Он просто позволяет вам делать obj.mood вместо obj.mood()

Ответ 3

Это по существу предпочтение. Он позволяет ввести object.property, а не object.property().

Итак, когда вы должны использовать это? Вы должны использовать контекст для принятия решения. Если метод, который у вас есть, возвращает значение, основанное на свойствах объекта, он экономит время создания переменной и устанавливает ее равным некоторому методу генератора (пример: property = object.generateProperty()). Не имеет смысла просто пропустить этот шаг и сделать generateProperty() свое собственное свойство?

Это общая концепция, как я ее понимаю.

Ответ 4

Это просто вопрос вкуса.

Свойство используется там, где доступ довольно дешев, например, просто запрашивает атрибут "private" или простой расчет.

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

Люди используются для использования методов getter и setter, но тенденция используется для использования свойств все больше и больше.

Возьмем, к примеру, класс Serial pyserial. Он имеет как методы наследия, такие как getBaudRate() и setBaudRate(), но рекомендует использовать baudrate как свойство чтения и записи для запроса и настройки скорости передачи.