2016-08-18 2 views
1

Gemäß der official documentation überschreiben "Datenattribute Methodenattribute mit demselben Namen". Ich fand das jedoch falsch.Überschreiben Datenattribute Methodenattribute in einer Klasse in Python?

class C: 
    x = 111 
    def x(self): 
     print('I am x') 
c = C() 
print(c.x) 

Die print-Anweisung im Code oben zeigt cx ein Verfahren ist, nicht das Datenattribut 111. So zugewiesen, zeigt dieser Code, dass das Datenattribut Methode nicht unbedingt überschreiben Attribute mit dem gleichen Namen und die Dokumentation falsch. Kann mir jemand meinen Befund bestätigen?

P.S. Ich habe den Code in Python 3.5 und Python 2.7 ausprobiert und das gleiche Ergebnis erhalten.

+2

Variablen können Schatten auf andere Variablen ... Methoden und Attribute und Klassen und Funktionen sind alle nur Variablen –

Antwort

3

Ich denke, die tutorial Leider ist (weil mehrdeutig) formuliert und durch

[d] ata Attribute überschreiben Methode mit dem gleichen Namen Attribute

bedeutet tatsächlich „Datenüberschreibung Attribute vorher zugeordnet/definierte Methodenattribute gleichen Namens und umgekehrt: Methodenattribute überschreiben zuvor zugeordnete/definierte Datenattribute gleichen Namens. "

„Duh“, Sie vielleicht denken, „Daten-Attribute auch vorher Daten Attribute mit dem gleichen Namen zugewiesen außer Kraft setzen, so was ist das Problem? Warum ist das einmal erwähnt?“ Das Zuweisen und Neuzuweisen (in dem zitierten Lernprogramm als "Überschreiben" bezeichnet) zu Variablen (ob sie "Attribute" von etwas oder nicht heißen) ist schließlich eines der prototypischen Merkmale einer imperativen Programmiersprache.

Nun, lassen Sie mich Ihnen vorstellen zu

Namespaces

Python Klassen Namespaces sind. Das Lernprogramm könnte also versuchen, hier zu sagen, dass die Datenattribute und Methodenattribute innerhalb einer Klasse einen Namespace teilen.

Dies gilt jedoch nicht für Attribute verschiedener Klassen. Wenn eine Klasse von einer anderen Klasse erbt, hat sie Zugriff auf die Namen ihrer Eltern. Wenn ein Name für die Methodendefinition oder die Datenzuweisung innerhalb der erbenden Klasse wiederverwendet wird, behält die übergeordnete Klasse die ursprünglichen Werte bei. In der Kinderklasse sind sie nur vorübergehend beschattet. Wenn Sie den Namen aus der untergeordneten Klasse entfernen, es auch wieder Zugriff auf das Attribut des gleichen Namen der Eltern bieten:

class A: 
     x = 111 

class B1(A): 
     x = 123 # Shadows A.x 

assert B1.x == 123 

del B1.x   # But after removing B1's own x attribute ... 
assert B1.x == 111 # ... B1.x is just an alias to A.x ! 


# Shadowing can happen at any time: 

class B2(A): 
     pass 

assert B2.x == A.x == 111 

B2.x = 5 # shadowing attributes can also be added after the class definition 

assert B2.x == 5 
assert A.x == 111 

del B2.x 
assert B2.x == A.x == 111 

Kontrast dies mit Neudefinition auch bekannt alsZu (oder „Überschreiben“, wie das Tutorial es nennt):

class C: 
     x = 555 
     def x(self): 
       print('I am x') 

C().x() # outputs "I am x" 

del C.x 
print(C.x) # AttributeError: 'C' object has no attribute 'x' 

Methode C.x() nicht vorübergehend Daten Schatten hat Attribut C.x. Er hat es ersetzt. Wenn wir also die Methode löschen, fehlt x vollständig innerhalb von C, anstatt dass das Datenattribut unter diesem Namen wieder erscheint.

Mehr Namespaces

Instanziierung fügt einen weiteren Namensraum und somit eine weitere Chance für Shadowing:

a = A() 
assert a.x == 111 # instance namespace includes class namespace 

a.x = 1000 
assert a.x == 1000 
assert A.x == 111 # class attribute unchanged 

del a.x 
assert a.x == 111 # sees A.x again 

In der Tat, alle (verschachtelte) Namensräume in Python arbeiten auf diese Weise: Pakete, Module, Klassen, Funktionen und Methoden, Instanzobjekte, innere Klassen, verschachtelte Funktionen ...

Beim Lesen einer Variablen wird die Namensraumhierarchie von unten nach oben durchlaufen, bis der Name gefunden wurde. (Hier lesen bedeutet bedeutet, den Wert (Objekt, Funktion/Methode oder Built-In) zu finden, an den der Name der Variablen gebunden ist. Wenn der Wert veränderbar ist, kann dieser auch zum Ändern des Werts verwendet werden.)

Ein Andererseits wird beim Setzen (Definieren oder Neudefinieren) einer Variablen ein Name des aktuellen Namensraums verwendet: Rebound auf den neuen Wert, wenn der Name bereits in diesem Namespace existiert (und nicht nur dort von einem anderen Namespace enthalten ist) oder a neu erstellter Name, falls dieser noch nicht existiert

+1

Es gibt auch eine andere Möglichkeit des Überschreibens/Shadowings: Methodendefinitionen enden im class-dict ('obj .__ class __.__ dict__'), während Instanzvariablen im instance-dict (' obj .__ dict__') landen. . Die Attributsuche findet zuerst im instance-dict statt und kann daher eine Methode mit demselben Namen überschatten, obwohl diese Methode immer noch im class-dict enthalten ist (keine tatsächliche Neuzuweisung). –

+1

@LukasGraf guter Punkt. Ich habe einen weiteren Abschnitt dazu hinzugefügt. –

+0

Vielen Dank für eine sehr klare und ausführliche Antwort. – candleindark

3

Attribute überschreiben Methoden und umgekehrt. Eine Faustregel ist, dass letztere die erstere außer Kraft setzt. Also, wenn Sie

class C: 
    x = 111 
    def x(self): 
     print('I am x') 
    x = 112 

c = C() 
print(c.x) 

tun Sie

erhalten
112 
+0

Bedeutet das, dass Sie damit einverstanden sind, dass die offizielle Dokumentation in dieser Angelegenheit falsch ist? – candleindark

+1

@candleindark dieser Satz in der Dokumentation ist zumindest sehr irreführend. Wie Kostas betonte, hebt eine spätere Aufgabe die erstere auf. Und * normalerweise *, Datenattribute (Instanzvariablen) werden zuerst in '__init __()' zugewiesen, weshalb sie später als Methodendefinitionen zugewiesen werden, die zugewiesen werden, wenn die Klassendeklaration analysiert wird. In Ihrem Beispiel verwenden Sie ein ** Klasse ** Level-Attribut, weshalb das "normalerweise" nicht gilt. –

-1

Sie wurden die zweite Definition von x fehlt, ist, warum es schien, wie die offizielle Dokumentation falsch war.

+1

Was meinst du mit der zweiten Definition von x? – candleindark

Verwandte Themen