Setter di non lavorare quando attributo inizia con "__"?

0

Domanda

Sto usando Python 3.8.6 e questo funziona bene

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

Questo non funziona

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

Che la mente che soffia. l'unica differenza tra il primo e il secondo esempio è che l'attributo private è __a invece di _a_

Qualche idea del perché? Non ero in grado di capirlo

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

Migliore risposta

1

È a causa di privati name mangling, ma non si applica al contenuto di valori letterali stringa come quella che si sta passando a getattr().

Fortunatamente la soluzione è semplice:

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

Penso che la variante utilizzo classname sarà la pausa per le sottoclassi, perché il setter è scritto nella classe base in modo che il nome dell'attributo sarà ancora alterati per _A__a.
kaya3

@kaya3: "break" e che senso? Esso utilizza il nome della sottoclasse in uno.
martineau

Beh, se class B(A): pass quindi b = B(); b._a = 23; print(b._a) stampa 0 perché il setter scrive _A__a ma il getter tenta di accedere a _B__a.
kaya3

@kaya3: Hai ragione, così ho rimosso quella parte della mia risposta.
martineau

In altre lingue

Questa pagina è in altre lingue

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