Perché il parametro "Nome" a __setTR__ include la classe, ma __geTattr__ non lo fa?

StackOverflow https://stackoverflow.com/questions/2386418

  •  24-09-2019
  •  | 
  •  

Domanda

Il seguente codice:

class MyClass():
    def test(self):
        self.__x = 0

    def __setattr__(self, name, value):
        print name

    def __getattr__(self, name):
        print name
        raise AttributeError(name)

x = MyClass()
x.test()
x.__y

Output:

_MyClass__x
__y
Traceback (most recent call last):
...
AttributeError: __y

La documentazione è assolutamente inutile affermare che il "nome" è il "nome dell'attributo", ma per qualche motivo è diverso a seconda che lo stia impostando o ottenendolo.

Quello che voglio sapere è:

  • Sto facendo qualcosa di fondamentalmente sbagliato qui?
  • Come ottengo x nel primo caso anziché _MyClass__x?
È stato utile?

Soluzione

Il doppio sottocore invoca il mangrezzo del nome. Se non hai bisogno di manglini di nome, non usare il doppio undescore

Qual è il significato di un singolo e un doppio controllo prima di un nome oggetto?

Dal Python Docs

9.6. Variabili private

Le variabili di istanza "privata" a cui non è possibile accedere, tranne dall'interno di un oggetto, non esistono in Python. Tuttavia, esiste una convenzione seguita dalla maggior parte del codice Python: un nome prefisso con un sottolineaggio (ad esempio _spam) dovrebbe essere trattato come una parte non pubblica dell'API (che si tratti di una funzione, un metodo o un membro dei dati). Dovrebbe essere considerato un dettaglio di implementazione e soggetto a modifiche senza preavviso.

Poiché esiste un caso d'uso valido per i membri della classe-privata (vale a dire per evitare scontri di nomi con nomi definiti dalle sottoclassi), esiste un supporto limitato per tale meccanismo, chiamato manglini. Qualsiasi identificatore della forma __spam (Almeno due principali punteggi, al massimo un sottolineabile) vengono sostituiti testualmente con _classname__spam, dove ClassName è il nome di classe corrente con le principali sottolineate (i) spogliate. Questo muscolo viene fatto senza riguardo alla posizione sintattica dell'identificatore, purché si verifichi all'interno della definizione di classe.

Si noti che le regole di mangling sono progettate principalmente per evitare incidenti; È ancora possibile accedere o modificare una variabile considerata privata. Ciò può anche essere utile in circostanze speciali, come nel debugger.

Notare che il codice è passato a exec, eval() o execfile() non considera il nome di classe della classe invocazione come la classe corrente; Ciò è simile all'effetto della dichiarazione globale, il cui effetto è anche limitato al codice che è compilato da byte insieme. La stessa restrizione si applica a getattr(), setattr() e delattr(), così come quando si fa riferimento __dict__ direttamente.

Altri suggerimenti

Non sono sicuro esattamente perché ciò accada, ma se usi _x piuttosto che __x Funziona come ti aspetteresti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top