2009-07-16 13 views
14

Questo è quello che sto cercando di fare in Python:Python eredità e genitore chiama costruttore di classe

class BaseClass: 
    def __init__(self): 
     print 'The base class constructor ran!' 
     self.__test = 42 

class ChildClass(BaseClass): 

    def __init__(self): 
     print 'The child class constructor ran!' 
     BaseClass.__init__(self) 

    def doSomething(self): 
     print 'Test is: ', self.__test 


test = ChildClass() 
test.doSomething() 

che si traduce in:

AttributeError: ChildClass instance has no attribute '_ChildClass__test' 

Che cosa dà? Perché non funziona come mi aspetto?

+0

call baseclass .-- init-- prima di fare qualsiasi altra cosa per riferimento futuro, –

risposta

20

Da documentazione python:

nome privato storpiatura: Quando un identificatore che si verifica testualmente in una definizione di classe inizia con due o più underscore caratteri e non termina con due o più underscore, si ritiene a nome privato di quella classe. I nomi privati ​​sono trasformati in un formato più lungo prima che il codice venga generato per loro. La trasformazione inserisce il nome della classe davanti al nome, con i caratteri di sottolineatura principali rimossi e una singola sottolineatura inserita davanti al nome della classe. Ad esempio, l'identificatore __spam che si verifica in una classe denominata Ham verrà trasformato in _Ham__spam. Questa trasformazione è indipendente dal contesto sintattico in cui viene utilizzato l'identificatore. Se il nome trasformato è estremamente lungo (più lungo di 255 caratteri), potrebbe verificarsi il troncamento definito dall'implementazione. Se il nome della classe consiste solo di caratteri di sottolineatura, non viene eseguita alcuna trasformazione.

Così il vostro attributo non è chiamato __test ma _BaseClass__test.

Tuttavia, non si deve dipendere da quello, utilizzare self._test, invece, e la maggior parte degli sviluppatori Python sapranno che l'attributo è una parte interna della classe, non è l'interfaccia pubblica.

+1

Ah ... quindi c'è un modo "giusto" o "pythonic" per accedere a quei membri privati ​​se ho bisogno di estendere una classe sta usando quella sintassi? –

+0

@Keith: È una domanda più OOP della domanda python. Accedendo a un membro privato di una superclasse, si interrompe l'incapsulamento e si crea una dipendenza molto forte tra le classi. Alla superclasse non è più permesso cambiare il suo funzionamento interno anche se l'interfaccia pubblica rimane la stessa.In breve: non farlo :) –

+0

Sfortunatamente, questo significa che o posso ri-scrivere la libreria smtpd di python, o copiare/incollare l'intera libreria smtpd in un nuovo file. Non voglio davvero fare nessuno di questi, ma ho bisogno di accedere alle variabili private delle librerie smtpd ... –

3

Le variabili doppie sottolineate possono essere considerate "private". Vengono mutilati con il nome della classe, tra l'altro per proteggere più oggetti di base dall'esecuzione forzata di ogni membro.

Utilizzare un trattino singolo se si desidera che il proprio attributo sia considerato privato da altri sviluppatori.

5

È possibile utilizzare le strutture di introspezione di Python per ottenere le informazioni desiderate. Un semplice dir (test) vi darà

['_BaseClass__test', '__doc__', '__init__', '__module__', 'doSomething'] 

Annotare il '_BaseClass__test'. Questo è quello che stai cercando.

Verificare this per ulteriori informazioni.

+0

Questa è metà della storia, come notato sopra, ma dir (unknown_thing) è sempre un buon passo. – taynaron

Problemi correlati