2013-02-15 14 views
5

consideri una classe con un metodo di "privato" come ad esempio:di override metodo del "privato" in Python

class Foo(object): 
    def __init__(self): 
     self.__method() 
    def __method(self): 
     print('42') 

Quando provo ad sottoclasse Foo e metodo di sostituzione __method, si può vedere che Foo.__method è ancora chiamato, invece di MoreFoo.__method.

class MoreFoo(Foo): 
    def __method(self): 
     print('41') 

>>> MoreFoo() 
42 
<__main__.MoreFoo object at 0x7fb726197d90> 

Quale sarebbe il modo di scavalcare un tale metodo?

+0

http://stackoverflow.com/questions/1301346/the-mating-of-a-single-and-a-double-underscore-before-an-object-name-in-python – tacaswell

+0

Fuori interesse, dove hai avuto l'idea che fosse equivalente a una variabile privata? È un malinteso davvero pessimo, e lo vedo sempre senza sapere da dove viene. –

+1

@Lattyware - Penso che provenga dalla sezione sui documenti chiamata "Variabili private e riferimenti locali di classe". Continua dicendo che non ci sono variabili private ... ma che la doppia sottolineatura è la cosa più vicina che puoi ottenere - "Poiché esiste un caso d'uso valido per i membri della classe privata (vale a dire evitare scontri sul nome dei nomi con nomi definiti da sottoclassi), esiste un supporto limitato per un tale meccanismo, ... " – mgilson

risposta

16

Il punto di utilizzando la convenzione di doppia sottolineatura nome è impedire sottoclassi da (accidentalmente) sostituire il metodo.

Se si avere per ignorarlo comunque, qualcuno ha commesso un grave errore di progettazione di classe. Si può fare ancora, per chiamare il vostro oggetto proprio così:

def _Foo__method(self): 

dove è prefisso il nome del metodo con un altro carattere di sottolineatura e il nome di classe che definisce (quindi in questo caso il prefisso _Foo). Il processo di ridenominazione di metodi e attributi con un trattino di sottolineatura doppio viene chiamato private name mangling.

Se si desidera definire un metodo "privato" che è ancora sovrascrivibile in una sottoclasse, in genere si applicano solo nomi con un carattere di sottolineatura (def _method(self):).

A causa della sua natura dinamica, quasi nulla in Python è veramente privato; con una piccola introspezione quasi tutto può essere raggiunto.

8

Un doppio prefisso di sottolineatura richiama il nome mangling, è non equivalente a un metodo privato. È progettato in modo specifico per evitare di essere sovrascritto dalle sottoclassi (e in questo caso, il nome del metodo diventa _Foo__method).

Se si dispone di un dettaglio di implementazione, è preceduto da un trattino singolo, questo è il segno universalmente accettato per i metodi Python che non devono essere utilizzati esternamente. Non c'è applicazione di questo, perché non è così che funziona Python.

+0

Sono consapevole che non è proprio privato, è per questo che ho scritto privato tra virgolette. –

+0

@ErnestA Non è solo che * non è proprio * privato, è che non è in alcun modo simile o comparabile - ricopre un ruolo completamente diverso. –

+0

Avevo l'impressione che fosse corretto chiamare i metodi che iniziano con 2 trattini bassi "privati". Forse non lo è. In questo caso mi dispiace per aver usato la terminologia sbagliata. –

3

credo che si dovrebbe fare qualcosa di simile:

class MoreFoo(Foo): 
    def _Foo__method(self): 
     print('41') 

come documented.

Qualsiasi identificatore della forma __spam (almeno due sottolineature importanti, al più un trattino basso in coda) viene testualmente sostituito con _classname__spam, dove classname è il nome della classe corrente con sottolineatura (s) messa a nudo.

Ma i progettisti della classe originale erano del parere che non si deve bisogno di fare qualcosa di simile come è difficile ignorare con sottoclassi è il punto di tutta la doppia sottolineatura per cominciare:

Il nome mangling è utile per consentire alle sottoclassi di sovrascrivere i metodi senza interrompere le chiamate al metodo intraclasse.

+0

Tecnicamente questo dovrebbe funzionare, ma maschera il problema più serio di abuso del doppio trattino basso in primo luogo. –

+0

@AndrewGorcester - Sicuro. Non sto dicendo che questa sia una buona idea. – mgilson

+0

Grazie. Non ho scritto la lezione originale. Voglio solo sovrascrivere uno dei suoi metodi che inizia con due underscore. –