Установщик свойств не работает, когда атрибут начинается с "__"?

0

Вопрос

Я использую Python 3.8.6, и это отлично работает

class A:
    @property
    def _a(self):
        return getattr(self, '_a_', 0)

    @_a.setter
    def _a(self, value):
        self._a_ = value


a = A()
print(a._a)  # prints 0
a._a = 10
print(a._a)  # prints 10 as expected

Это не работает

class A:
    @property
    def _a(self):
        return getattr(self, '__a', 0)

    @_a.setter
    def _a(self, value):
        self.__a = value

a = A()
print(a._a)  # prints 0
a._a = 10
print(a._a)  # prints 0 again

Это сногсшибательно! единственное различие между первым и вторым примером заключается в том, что атрибут private является __a вместо _a_

Есть идеи, почему? Я не смог этого понять

properties python
2021-11-20 09:49:15
1

Лучший ответ

1

Это связано с искажением личных имен, но это не относится к содержимому строковых литералов, подобных тому, к которому вы переходите getattr().

К счастью, исправить это просто:

class A:
    @property
    def _a(self):
        return getattr(self, '_A__a', 0)

    @_a.setter
    def _a(self, value):
        self.__a = value

a = A()
print(a._a)  # prints 0
a._a = 10
print(a._a)  # prints 10 now
2021-11-20 15:39:03

Я думаю, что вариант с использованием classname будет нарушен для подклассов, потому что задатчик записан в базовом классе, поэтому имя атрибута все равно будет искажено до _A__a.
kaya3

@kaya3: "ломать" это какой смысл? Он использует имя подкласса в одном.
martineau

Что ж, если class B(A): pass затем b = B(); b._a = 23; print(b._a) напечатает 0 потому что сеттер пишет _A__a но получатель пытается получить доступ _B__a.
kaya3

@kaya3: Вы правы, поэтому я удалил эту часть своего ответа.
martineau

На других языках

Эта страница на других языках

Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................