Setter de la propriété ne fonctionne pas lorsque l'attribut commence par "__"?

0

La question

Je suis à l'aide de Python 3.8.6 et cela fonctionne bien

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

Cela ne fonctionne pas

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

C'est hallucinant! la seule différence entre le premier et le deuxième exemple est celui de l'attribut privé est __a au lieu de _a_

Aucune idée pourquoi? Je n'étais pas en mesure de le comprendre

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

La meilleure réponse

1

C'est en raison de privé nom d'amputation, mais il ne s'applique pas au contenu de littéraux de chaîne comme celle que vous êtes de passage à getattr().

Heureusement, la solution est simple:

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

Je pense que la variante en utilisant classname pause pour les sous-classes, parce que le setter est écrit dans la classe de base de sorte que le nom de l'attribut sera toujours mutilé à _A__a.
kaya3

@kaya3: "briser" il quel sens? Il utilise le nom de la sous-classe dans un.
martineau

Eh bien, si class B(A): pass alors b = B(); b._a = 23; print(b._a) imprime 0 parce que le compositeur écrit _A__a mais la lecture essaie d'accéder à _B__a.
kaya3

@kaya3: Vous avez raison, donc j'ai supprimé cette partie de ma réponse.
martineau

Dans d'autres langues

Cette page est dans d'autres langues

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