2013-09-27 3 views
8

Ich habe den folgenden Code.Warum erbt die untergeordnete Klasse in diesem Beispiel nicht die Methode von der übergeordneten Klasse in Python?

class Foo(object): 
    def __init__(self): 
     self.__baz = 40 
    def foo(self): 
     print self.__baz 

class Bar(Foo): 
    def __init__(self): 
     #super(Bar, self).__init__() 
     self.__baz = 21 
    def bar(self): 
     print self.__baz 

x = Bar() 
x.foo() 
x.bar() 

ich diesen Fehler:

Traceback (most recent call last): 
    File "classes.py", line 15, in <module> 
    x.foo() 
    File "classes.py", line 5, in foo 
    print self.__baz 
AttributeError: 'Bar' object has no attribute '_Foo__baz' 

warum ist die foo Methode nicht in Bar geerbt.

EDIT: Es funktioniert gut, wenn Sie Super anrufen, die auskommentiert ist.

+3

Nicht sicher, aber nicht weil __variablename eine spezielle Variable ist? http://StackOverflow.com/a/1301369/2537322 – meyer9

+0

Kurioser, warum funktioniert es, wenn Sie 'super()' nennen? –

+0

Keine Antwort, aber fügt mehr Details hinzu - wenn Sie es von "__baz" zu "baz" ändern, drucken beide Aufrufe 21. Wenn Sie 'super()' aufrufen und als '__baz 'belassen, drucken sie' 40' und '21' beziehungsweise. –

Antwort

7

Die Doppelstrich Attribute haben ihre Namen basierend auf dem Strom/enthält Namespace verstümmelt. In der Funktion foo ist der aktuelle Namespace Foo, also wenn Python self.__baz nachschlägt, wird es tatsächlich nach aufgrund des Namens Mangling-Schema suchen. Da nirgendwo in Foo haben Sie tatsächlich ein __baz Attribut festgelegt, hat die Klasse keine _Foo__baz Attribut (es hat ein _Bar__baz Attribut seit Sie self.__baz in einer Methode innerhalb Bar setzen).

Natürlich, wie Sie wahrscheinlich bemerkt haben, wenn Sie Foo.__init__(self) rufen in Baz.__init__ (direkt oder über super), sehen Sie, das Problem gehen weg, weil Foo.__init__ Sätze __baz (das heißt _Foo__baz).

+0

also ist die foo-Methode nicht korrekt geerbt? Ich bin etwas verwirrt darüber, was hier passiert ... –

+0

@ user1988876 - die 'foo' Methode * ist * vererbt. Aber wenn Sie es aufrufen, ist das Attribut, auf das es zuzugreifen versucht, * fehlt *. Wenn Python 'self .__ baz' innerhalb der Definition der' Bar'-Klasse sieht, wird es in 'self._Bar__baz' geändert. Wenn es 'self .__ baz' in der Definition der' Foo' Klasse sieht, wird es in 'self._Foo__baz' geändert. Die ganze Idee hier ist so, dass "self .__ baz" in "Foo" sich von "self .__ baz" in "Bar" unterscheiden kann. – mgilson

+0

Also eigentlich wenn er 'Super (Bar, Selbst) nennt.__init __() 'Kind Klasse Bar-Objekt hat ** zwei ** Attribute eine ist' _Bar__baz' (weil er 'self .__ baz = 21' in Child-Klasse Init-Methode) und andere ist' _Foo__baz' von Eltern-Klasse **? * * Im Fehlerfall (wenn er nicht 'super (Balken, self) .__ init __()' nennt) hat das Objekt von Bar nur ein Attribut, das '_Bar__baz' ** ist? ** –

3

Wenn Sie Variablen mit doppeltem Unterstrich wie in Python benennen, wird der Mitgliedsname verschleiert. Wenn Sie __baz deklarieren, erhalten Sie ein Mitglied _Bar__baz.

class Bar(Foo): 
def __init__(self): 
    #super(Bar, self).__init__() 
    self.__baz = 21 
def bar(self): 
    print self._Bar__baz 

x = Bar() 
x.bar() 
>>> 21 
+0

Sie haben die Definition der Funktion 'bar' geändert. Ich würde gerne wissen, warum es funktioniert, wenn der Superruf gemacht wird, wie ich in meinem Edit –

+0

+ gemacht habe, wie Sie einen Trick hinzugefügt, der für mich hilfreich ist, aber ist es nicht schlechte Praxis, '_Bar__baz' explizit **? * * –

Verwandte Themen