BlackJack hat geschrieben:@würmchen: Wenn Du nicht weisst was das tut, dann ist das "programming by accident", funktioniert halt zufällig. Wobei ich mir bei dem Quelltext und deinem letzten Beitrag auch nicht so ganz sicher bin, dass Du Klassen und Instanzen ordentlich auseinander hältst und das es wirklich so funktioniert wie es soll.
So wie das da jetzt steht hat `Query` 4 Klassenvariablen und keine einzige Instanzvariable. Sprich *alle* Instanzen von `Query` teilen sich die gleichen Werte. Und das `y` wird zu einer Klassenvariablen von der Unterklasse von der aus die `Query.__init__()` aufgerufen wird. Das ist eine sehr seltsame Konstruktion um es mal vorsichtig aus zu drücken.
Ok, ich kopier den Abschnitt aus dem Buch mal hier rein....
Was geplant ist, ist eine Zählerklasse zu bauen, die dann später an andere Klassen vererbt werden kann. Gezählt wird, wieviele Instanzen einer Klasse existieren....
Galileo Buch hat geschrieben:Wir wollen nun das angegebene Beispiel in Python implementieren, wobei wir uns zuerst der Zaehler-Klasse zuwenden:
Code: Alles auswählen
class Zaehler(object):
Anzahl = 0
def __init__(self):
type(self).Anzahl += 1
def __del__(self):
type(self).Anzahl -= 1
Galileo Buch hat geschrieben:Die Definition enthält bis auf den Zugriff auf das Attribut Anzahl mittels type(self) nichts Neues. Wir können deshalb nicht mehr direkt über den Klassennamen per Zaehler.Anzahl auf das Attribut zugreifen, weil wir von der Klasse erben wollen und die Subklassen jeweils ihr eigenes statisches Attribut Anzahl haben sollen. Würden wir mit Zaehler.Anzahl arbeiten, könnten wir damit die Gesamtanzahl der Konto- und Angestellter-Instanzen berechnen. Mithilfe von type lässt sich der Datentyp einer Instanz ermitteln, und das nutzen wir, um den Zähler abhängig davon, welchen Typ self hat, für die richtige Klasse zu ändern
Galileo Buch hat geschrieben:Nun wollen wir unsere Konto-Klasse von Zaehler erben lassen:
Code: Alles auswählen
class Konto(Zaehler):
def __init__(self, inhaber, kontonummer, kontostand,
max_tagesumsatz=1500):
Zaehler.__init__(self) # Wichtige Zeile - siehe unten
self.__Inhaber = inhaber
self.__Kontonummer = kontonummer
self.__Kontostand = kontostand
self.__MaxTagesumsatz = max_tagesumsatz
self.__UmsatzHeute = 0
# hier wären die restlichen Methoden
Galileo Buch hat geschrieben:Im Wesentlichen haben sich bei der neuen Definition von Konto nur das schon angesprochene Ersetzen von object durch Zaehler und die erste Zeile des Konstruktors geändert. Mit Zaehler.__init__(self) rufen wir den Konstruktor der Basisklasse auf, um unser Konto auch als Zähler benutzen zu können. Dies ist deshalb notwendig, weil eine Klasse nur eine Methode __init__ haben kann. Bei der Vererbung tritt nun oft der Fall ein, dass die erbende Klasse Methoden definiert, die auch schon in der Basisklasse vorhanden waren – in unserem Beispiel eben der Konstruktor __init__. In einem solchen Fall werden die Methoden der Basisklasse mit denen, die die Subklasse selbst definiert, überschrieben, sodass im Beispiel self.__init__ eine Referenz auf den Konstruktor von Konto und nicht auf den von Zaehler enthält. Um trotzdem auf solche überschriebenen Methoden zugreifen zu können, ersetzt man beim Aufruf das self vor dem Punkt durch den Namen der entsprechenden Basisklasse und übergibt self explizit als Parameter. Würde Zaehler.__init__ noch weitere Parameter erwarten, so würden diese wie üblich durch Kommata getrennt dahinter geschrieben.
Und wenn ich das was die da gemacht haben richtig verstanden habe, benutzen die dieses type(this) Konstrukt um die Klassenvariable irgendwie als Instanzvariable zu nutzen.
Im Großen und ganzen sind mir aber die Unterschiede zwischen Instanz und Klasse schon bewusst. Nur dieses Beispiel hat mich verwirrt.