Когда мне следует определять методы получения для python свойств? - PullRequest
2 голосов
/ 06 августа 2020

Меня немного смущает полезность синтаксиса python @*.getter по сравнению с простым определением свойства без геттера.

Чтобы исследовать это, давайте напишем очень простой класс:

class Foo:

    def __init__(self):
    
        self._x = None

    @property
    def x(self):
        print('Attribute `self.x` is a property.')
        return self._x

    @x.getter
    def x(self):
        print('Getting property `x`...')
        return self._x

Теперь, если я попытаюсь создать экземпляр класса и получить свойство x из экземпляра, мы увидим, что вызывается метод получения:

>>> A = Foo()
>>> print(A.x)
Getting property `x`...
None

Хорошо, и что? Это именно то, что мы должны ожидать.

Однако, если я определю точно такой же класс без любого метода получения, мы получим что-то другое:

>>> print(A.x)
Attribute `self.x` is a property.
None

Когда нет Метод getter определен, попытка получить свойство приводит к тому, что вместо этого вызывается метод определения свойства (я имею в виду метод, определенный в @property, из-за отсутствия лучшего имени).

Интересно, что в В первом случае метод, определенный в @property, на самом деле никогда не вызывается.

Итак, какой смысл иметь специальный метод получения, если исходное определение свойства, кажется, служит геттером в его отсутствие? Служит ли исходное определение какой-либо цели, кроме как просто сказать: «это свойство»? Существуют ли какие-либо другие обстоятельства, при которых этот метод будет вызван (кроме получения свойства при отсутствии геттера)? Почему вы решили использовать геттер вместо простого включения его функций в определение свойства?

Наконец, есть ли какие-либо варианты использования, когда можно было бы использовать метод определения свойства, который является более сложным, чем следующая каноническая форма, при использовании метода @*.getter?

@property
def x(self): return self._x

1 Ответ

1 голос
/ 07 августа 2020

Использование декоратора @x.getter сообщает Python, что следующий метод является предполагаемым получателем для свойства.

Вы правы, что он не очень полезен в приведенном вами примере. Декоратор @property выполняет ту же работу и определяет свойство в одном go. На самом деле нет причин использовать оба в одном определении класса.

Однако, возможно, вы хотите переопределить метод получения в подклассе?

class Foo:
    def __init__(self, x):
        self._x = x

    @property
    def x(self):
        print('Attribute `self.x` is a property.')
        return self._x


class Bar(Foo):
    count: int = 0

    @Foo.x.getter
    def x(self):
        Bar.count += 1
        print(f'Getting Bar property `x` ({Bar.count})')
        return self._x


foo = Foo(10)
print(foo.x)
bar = Bar(10)
print(bar.x)
print(bar.x)

Вывод:

Attribute `self.x` is a property.
10
Getting Bar property `x` (1)
10
Getting Bar property `x` (2)
10

Есть несколько других вариантов использования, в которых определение получателя явно имеет смысл, даже если в базовом случае вы просто используете @property и @attr.setter.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...