Трудно понять, как @property знает, какая переменная является свойством? - PullRequest
1 голос
/ 30 января 2020

Я недавно узнал о декораторе @property, но есть (по крайней мере) одна вещь, которую я еще не понимаю об этом. В этом классе ниже my_name, очевидно, является именем свойства, но не совсем понятно, как на самом деле присваивается значение. Единственные назначения - это подчеркнутая переменная _my_name, но как декоратор узнает, что self._my_name соответствует свойству my_name?

class Person:
    def __init__(self, input_name):
        self._my_name = input_name

    @property
    def my_name(self):
        return self._my_name

    @my_name.setter
    def my_name(self, value):
        self._my_name = value

Ответы [ 2 ]

1 голос
/ 30 января 2020

Попробуйте посмотреть так: декоратор не знает ничего о внутренностях класса ex: self._my_name. Что он знает , так это то, что функция должна вызывать при получении или установке значения.

p = Person('bob')
name = p.my_name     ## the 'getter' function is called: ultimately p.my_name(self)
p.my_name = 'alice'  ## the 'setter' function is called: ultimately p.my_name(self, 'alice')

Здесь, под капотом, происходит еще больше вещей. Посмотрите на похожий вопрос: Как работает декоратор @property? Верхний ответ действительно хорошо объясняет, что такое @property.

0 голосов
/ 30 января 2020

A property является дескриптором . Он знает, где взять и установить _my_name, потому что это то, что ваши методы получения и установки говорят ему получить и установить. Вот простой пример того, как дескриптор внутренне работает:

class MyProperty:
    def __init__(self, name):
        # The name of the property we are wrapping
        self.name = name

    def __get__(self, instance, owner):

        # Property was requested from the class, not an instance
        if instance is None:
            return self

        return getattr(instance, self.name)

    def __set__(self, instance, value):

        # Don't overwrite ourself...
        if instance is None:
            return

        setattr(instance, self.name, value)


class Person:
    def __init__(self, input_name):
        self._my_name = input_name

    # Define my_name, that will get/set _my_name
    my_name = MyProperty('_my_name')

jack = Person('Jack')
print(jack.my_name)
jack.my_name = 'Jane'
print(jack.my_name)

Свойство работает аналогичным образом, где он запоминает свои определенные обратные вызовы getter, setter и delete и вызывает их, когда дескриптор получен / назначен.

...