2009-07-16 4 views
14

C'est ce que je suis en train de faire en Python:Python et appelant constructeur de la classe parent

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() 

qui se traduit par:

AttributeError: ChildClass instance has no attribute '_ChildClass__test' 

Qu'est-ce qui se passe? Pourquoi cela ne fonctionne-t-il pas comme prévu?

+0

appel baseclass .-- init-- avant de faire quoi que ce soit d'autre pour référence future, –

Répondre

20

De la documentation python:

Nom privé mangling: Quand un identifiant qui se produit textuellement dans une définition de classe commence par deux ou plus, soulignent caractères et ne se termine pas dans deux ou plusieurs underscores, il est considéré comme nom privé de cette classe. Les noms privés sont transformés en une forme plus longue avant que le code soit généré pour eux. La transformation insère le nom de la classe devant le nom, les traits de soulignement supprimés et un trait de soulignement inséré devant le nom de la classe. Par exemple, l'identifiant __spam apparaissant dans une classe nommée Ham sera transformé en _Ham__spam. Cette transformation est indépendante du contexte syntaxique dans lequel l'identifiant est utilisé. Si le nom transformé est extrêmement long (plus de 255 caractères), la troncation définie par l'implémentation peut se produire. Si le nom de la classe ne comporte que des traits de soulignement, aucune transformation n'est effectuée.

Ainsi, votre attribut n'est pas nommé __test mais _BaseClass__test. À la place, utilisez plutôt self._test et la plupart des développeurs python savent que l'attribut est une partie interne de la classe, pas l'interface publique.

+1

Ah ... il y a donc un moyen "juste" ou "pythonique" pour accéder à ces membres privés si j'ai besoin d'étendre une classe c'est en utilisant cette syntaxe? –

+0

@Keith: C'est une question plus OOP que la question python. En accédant à un membre privé d'une superclasse, vous rompez l'encapsulation et vous créez une dépendance très forte entre les classes. Superclass n'est plus autorisé à modifier son fonctionnement interne même si l'interface publique reste la même.En résumé: ne faites pas ça :) –

+0

Malheureusement, cela signifie que je peux soit réécrire la bibliothèque python smtpd, soit copier/coller toute la bibliothèque smtpd dans un nouveau fichier. Je ne veux pas vraiment faire l'un ou l'autre, mais j'ai besoin d'accéder aux variables privées des bibliothèques smtpd ... –

3

Les doubles variables soulignées peuvent être considérées comme "privées". Ils sont mutilés avec le nom de classe, entre autres pour protéger plusieurs baseclasses de surcharger les autres membres. Utilisez un trait de soulignement unique si vous souhaitez que votre attribut soit considéré comme privé par d'autres développeurs.

5

Vous pouvez utiliser les fonctions d'introspection de Python pour obtenir les informations que vous recherchez. Un dir simple (test) vous donnera

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

Notez le '_BaseClass__test'. C'est ce que vous cherchez.

Vérifiez this pour plus d'informations.

+0

C'est la moitié de l'histoire, comme indiqué ci-dessus, mais dir (unknown_thing) est toujours un bon pas. – taynaron

Questions connexes