Utilizzo di __ pur dichiarando qualsiasi variabile o membro della classe in python

3

È buona norma usare la convenzione __ mentre si dichiara la variabile membro?

Questo conferisce anche un tipo privato di funzionalità di quel membro dati. Ci sono stati casi in cui ho scoperto che è bello avere membri nascosti di una classe. Questo di sicuro espone solo quella caratteristica che aiuterà l'oggetto a comportarsi in modo più protetto.

    
posta Bhupesh Pant 21.02.2014 - 10:16
fonte

4 risposte

10

Un sacco di persone usano erroneamente caratteri di sottolineatura doppio per simulare membri "privati", perché i doppi underscore richiamano il mangling del codice e rendono più difficili i riferimenti ai membri al di fuori della classe. Tuttavia, in realtà non li rende inaccessibili.

Il più delle volte, aggiunge principalmente un bump stradale al test dell'unità.

In realtà il doppio meccanismo di manomissione del sottotitolo è quello di nascondere quei membri da sottoclassi che non si desidera che i valori vengano ignorati inavvertitamente. Il nome mangling non ha lo scopo di nascondere il membro ad altri programmatori; lo schema di mangling è semplice, e fare riferimento alle variabili è comunque facile.

Un singolo trattino basso è la convenzione comune per i membri interni. Questo vuol dire che siamo tutti adulti qui, e sebbene tu possa vederlo, questa variabile è intesa per uso interno. Se fai riferimento a questo, non è garantito che sarà ancora presente nelle versioni future.

Il doc Pep8 ne parla, e dice che l'uso dei doppi underscore per variabili e funzioni dovrebbe essere davvero raro.

    
risposta data 21.02.2014 - 10:45
fonte
9

La funzione è specificatamente pensata per prevenire gli scontri accidentale tra un membro della classe genitore e sottoclassi.

Il nome viene manomesso anteponendolo con il nome della classe; l'atribute __foo su una classe Bar diventa _Bar__foo , e può ancora essere accessibile come tale dall'esterno.

Questo rende oscurato al meglio, non privato. L'unico caso d'uso reale per tali attributi è per gli attributi dei membri che sono legati all'implementazione specifica di un metodo di classe genitore che una sottoclasse potrebbe sovrascrivere accidentalmente con la propria versione.

    
risposta data 21.02.2014 - 10:47
fonte
2

Aggiunta alla risposta di Rob Y: molti pensano che l'uso del doppio trattino basso impedisca il superamento del metodo, ma non è vero:

class Me(object):
    def override_me(self):
        print "Me: I should NOT be called"

    def __dont_override_me(self):
        print "Me: I SHOULD be called"

class OverrideMe(Me):
    def override_me(self):
        print "OverrideMe: I SHOULD be called"

    def __dont_override_me(self):
        print "OverrideMe: I should NOT be called"


me = Me()
override = OverrideMe()

me._Me__dont_override_me()
override.override_me()
override._OverrideMe__dont_override_me()

Output:

Me: I SHOULD be called
OverrideMe: I SHOULD be called
OverrideMe: I should NOT be called

Dipende da come lo si accede e non ha nulla a che fare con la prevenzione dell'override.

Tuttavia, il nome mangling mi impedisce .__ dont_override_me () di essere chiamato, poiché genererebbe un errore di attributo:

me.__dont_override_me()

Output:

Traceback (most recent call last):
  File "/private/tmp/stackoverflow.py", line 23, in <module>
    me.__dont_override_me()
AttributeError: 'Me' object has no attribute '__dont_override_me'
    
risposta data 24.03.2016 - 11:10
fonte
-1

Il commento fatto da Alex Punnen non è corretto, ma sfortunatamente non ho il punto di reputazione per aggiungere commenti lì. Quello che cerca di fare è abusare dell'assunzione del "uomo adulto" di Python per chiamare direttamente i metodi storpiati, il che non è quello che dovrebbe essere fatto comunque. In ogni caso, se si scrive un nuovo metodo __dont_override_me in una sottoclasse, non si ottiene la sovrascrittura. Si verifica invece un sovraccarico: un metodo non correlato con lo stesso nome. La differenza chiave è che il codice "vecchio", cioè il codice nella classe base Me, non (normalmente, a meno che non si usi direttamente il nome storpiato) chiama quel nuovo metodo. Nel suo esempio:

class Me(object):
    def override_me(self):
        print "Me: I should NOT be called"

    def not_overriden(self):
        self.__dont_override_me()

    def __dont_override_me(self):
        print "Me: I SHOULD be called"

class OverrideMe(Me):
    def override_me(self):
        print "OverrideMe: I SHOULD be called"

    def __dont_override_me(self):
        print "OverrideMe: I should NOT be called"

me = Me()
override = OverrideMe()

me.override_me()
me.not_overriden()
override.override_me()
override.not_overriden()

Viene eseguito con il seguente risultato:

Me: I should NOT be called
Me: I SHOULD be called
OverrideMe: I SHOULD be called
Me: I SHOULD be called
    
risposta data 22.11.2016 - 04:15
fonte

Leggi altre domande sui tag