Propriedade setter não funcionar quando o atributo começa com "__"?

0

Pergunta

Eu estou usando Python 3.8.6 e isso funciona bem

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

Isto não funciona

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

Que o sopro da mente! a única diferença entre o primeiro e o segundo exemplo é o de que o atributo é privado __a em vez de _a_

Alguma idéia de por que? Eu não era capaz de descobrir

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

Melhor resposta

1

É devido a privada desconfiguração do nome, mas ela não se aplica ao conteúdo de literais de seqüência de caracteres como o que você está passando para getattr().

Felizmente, a correção é simples:

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

Eu acho que a variante usando classname vai quebrar por subclasses, porque o enunciador está escrito na classe base para o atributo nome ainda vai ser deturpados para _A__a.
kaya3

@kaya3: "quebrar" que sentido? Ele usa o nome da subclasse em um.
martineau

Bem, se class B(A): pass em seguida, b = B(); b._a = 23; print(b._a) irá imprimir 0 porque o compositor escreve _A__a mas o getter tenta acessar _B__a.
kaya3

@kaya3: Você está certo, assim que eu removi a parte de minha resposta.
martineau

Em outros idiomas

Esta página está em outros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................