Seite 1 von 1
Klassen und erben
Verfasst: Dienstag 20. Oktober 2009, 11:04
von Seeker
Hi!
Ich habe irgendwie besonders Mühe mit Klassen =/. Ich hab also zum x-ten mal das Tutorial darüber gelesen, und verstehe nun schon etwas besser, wann self. kommt usw.
Ich komm aber irgendwie nicht weiter mit dem "erben" (mal naiv direkt übersetzt ^^).... Die Idee dahinter verstehe ich zwar, aber praktisch klappts irgendwie nicht ganz =).
Hier ein kleines Script, wo ich Klassen und deren Funktionen auf verschiedene Arten definiere / aufrufe (mir ist bewusst, dass man eine Funktion nie ausserhalb der eigenen Klasse definieren sollte, aber es ging mir nur ums Verständnis, wie es gehen würde):
Code: Alles auswählen
def second(self):
print self.y
class Bass_Class:
def __init__(self, x, y):
self.x = x
self.y = y
def first(self):
print self.x
second = second
class First_Derived_Class(Bass_Class):
def __init__(self, z):
self.z = z
def third(self):
print self.z
def fourth(self):
Bass_Class.__init__(self, "Hi, fourth #1", "Hi, fourth #2")
print self.x
print self.y
class Second_Derived_Class(Bass_Class):
def __init__(self, x, y, v):
Bass_Class.__init__(self, x, y)
self.v = v
self.args = (x, y, v)
def fifth(self):
for i in self.args:
print i
b = Bass_Class("Hi, this is the first message", "This is the second")
d = First_Derived_Class("And this is the third")
s = Second_Derived_Class("Hi, this is the first message again", "This is the second again", "This is the fifth")
b.first()
b.second()
d.third()
d.fourth()
s.first()
s.fifth()
Nun meine Schwierigkeiten:
1. Wenn ich die Bass_Class.__init__() in der First_Derived_Class aufrufe (Zeile 18), muss ich x und y wieder "definieren". Wie kann ich machen, dass eben das x und y nur einmal definieren muss, und diese Zuordnung dann eben geerbt wird? =/
[EDIT... hab mir Frage 2 gerade selbst beantwortet^^]
Danke für ein bisschen Hilfe & Kritik =).
lg Seeker
PS: entschuldigt die leicht chaotischen Variabelnamen... :/
Verfasst: Dienstag 20. Oktober 2009, 11:11
von snafu
Wenn du die `__init__()`-Methode der Klasse, von der du erbst, überschreibst, dann musst du auch wieder alle Namen übernehmen. Das macht Python nicht von alleine. Oft erbt man ja, weil man nur eine einzelne Methode überschreiben möchte. Man sollte es mit der Vererbung IMHO sowieso nicht übertreiben. Häufig ist es besser, die zusätzliche Klasse als Attribut zu verwenden.
Verfasst: Dienstag 20. Oktober 2009, 11:40
von CM
snafu hat geschrieben: Häufig ist es besser, die zusätzliche Klasse als Attribut zu verwenden.
Du hast schon recht, doch hier möchte ich die Aussage modifzieren, denn das ist die Frage nach Haben und Sein: Hat die Klasse ein Objekt (bzw. eine Instanz einer anderen Klasse) als Attribut oder ist die betreffene Klasse etwas Ähnliches wie eine "Oberklasse"? Im ersten Fall vererbt man nicht, im zweiten mitunter schon. Es kommt also drauf an - wie fast immer

.
Aber ich bin mir sicher, das hast Du gemeint.
Verfasst: Dienstag 20. Oktober 2009, 11:50
von crs
bin mir jetzt nicht ganz sicher ob ich die frage richtig verstanden habe, aber evtl. suchst du
*arguments bzw. **keywords?
Code: Alles auswählen
class Foo(object):
def __init__(self, x, y):
self.x = x
self.y = y
class Bar(Foo):
def __init__(self, z, *args, **kwargs):
Foo.__init__(self, *args, **kwargs)
self.z = z
ob vererbung dann in einem speziellen fall auch wirklich sinnvoll ist oder nicht ist natuerlich nochmal eine andere frage, so allgemein kann man dazu aber eigentlich keine wirkliche aussage machen.
und p.s.: BaseClass, nicht Bass_Class

Verfasst: Dienstag 20. Oktober 2009, 13:04
von Seeker
Danke für die Antworten =).
Alles klar... zu viele Klassen und Unterklassen sind also oft vermeidbar

. Aber viele Python Programme, die ich gesehen habe, arbeiten trotzdem mit Klassen (und z.T. Unterklassen), und ich wollte einfahc die Syntax verstehen =).
@crs:
Also, das *args und **kwargs geben mir einfach die Möglichkeit, eine unbestimmte Anzahl Argumente einzufügen, oder?
Ich verstehe vor allem nicht, wie ich in der Oberklasse definierte Variabeln in der Unterklasse nutzen kann.
Bsp.
Oberklasse macht irgendwas mit x und y. Etwas später kommt dann die Unterklasse mit einer dritten Variabel z, wobei ich aber x und y auch wieder brauche.
Eine Anwendung könnte z.B. sein, dass man immer x und y hat, aber je nach dem, was für ein Objekt man verarbeitet (also z.B: Dateityp), muss man etwas anderes machen.
Dann könnte man eine Oberklasse mit x und y kreieren, und dann eine Reihe von Unterklassen, die dann mit x, y und einer neuen Variable z etwas anstellen.
Code: Alles auswählen
class Foo:
def __init__(self, x, y):
self.x = x
self.y = y
class Bar(Foo):
def __init__(self, z):
Foo.__init__(self, x, y) ##Werte werden aus Foo genommen, ich muss sie nicht neu definieren
self.z = z
def add(self):
print (self.x + self.y +self.z)
##(wobei x und y aus Foo() sind, ich möchte die gleichen Werte weiterverwenden)
##Aufrufen müsste dann irgendwie so aussehen:
f = Foo(10, 20)
b = Bar(30) ##--> die werte von x und y werden durch das Foo.__init__(self, x, y) also gleich übernommen.
b.add()
##Ausgabe:
60
Ist das überhaupt möglich ?
Verfasst: Dienstag 20. Oktober 2009, 13:10
von ms4py
Ähm nein nicht direkt...
Du musst natürlich die Werte in der Klasse setzen
Bar.__init_ muss so aussehen
Ich glaube du hast das Vererbungsprinzip nicht richtig verstanden.
Vermutlich willst du so was:
Code: Alles auswählen
class Foo(object):
def __init__(self, x, y):
self.x = x
self.y = y
class Bar(object):
def __init__(self, z, foo)
self.z = z
self.foo = foo
print foo.x, foo.y, z
foo = Foo(1,2)
bar = Bar(3, foo)
Verfasst: Dienstag 20. Oktober 2009, 13:22
von Seeker
hm... also muss ich zwingend wieder x und y neu angeben?
Ich kann einfach die "Verarbeitung" von x und y übernehmen, aber die Werte können nicht "vererbt" werden?

In meinem Fall mit den Dateitypen würde man die Oberklasse also gar nie aufrufen... sondern direkt die Unterklasse aufrufen, wobei x und y einfach durch die Oberklasse verarbeitet werden?
Dann wär ja einiges klarer

... danke

!
Ich hatte das mit dem "erben" wohl falsch verstanden.
lg Seeker
EDIT: War ich wohl zu langsam. Genau das hatte ich (falsch) gemeint.

Verfasst: Dienstag 20. Oktober 2009, 13:31
von Hyperion
Wie sollte denn so was gehen, wie Du es Dir vorstellst?
Ich greife mal Dein Beispiel auf:
Code: Alles auswählen
f = Foo(10, 20)
b = Bar(30)
# b.x=10, b.y=20, b.z=30
another_f = Foo(100, 200)
another_bar = Bar(300)
# welche Werte bekommt denn nun another_bar?
# Die von f oder another_f?
Selbst wenn man obiges irgend wie per Konvention lösen könnte, so bliebe ja die Einschränkung, dass man um ein Objekt einer tiefsten Klasse anlegen zu können, erst einmal für jede Eltern-Klasse ein neues Objekt anlegen müßte... das wäre nicht grad toll, oder?

Verfasst: Dienstag 20. Oktober 2009, 13:43
von Seeker
Ja, ich sehe das Problem =), ich verstehe ja jetzt au den Sinn des ganzen besser

.
Aber mal nur als Argument:
Man könnte Unterklassen z.B. irgendwie so machen:
Dann würde per default das x und y von der Oberklasse genommen, aber man könnte trotzdem neuen Werte eingeben.
Aber ich schätze, dass man dies irgendwie mit
Code: Alles auswählen
def Bar:
def __init__(self, z, x = Foo.x, y = Foo.y):
self.x = x
self.y = y
self.z = z
machen
Verfasst: Dienstag 20. Oktober 2009, 13:49
von Hyperion
Seeker hat geschrieben:Ja, ich sehe das Problem =), ich verstehe ja jetzt au den Sinn des ganzen besser

.
Aber mal nur als Argument:
Man könnte Unterklassen z.B. irgendwie so machen:
Dann würde per default das x und y von der Oberklasse genommen, aber man könnte trotzdem neuen Werte eingeben.
Du verwechselst da noch Klassen und Objekte von Klassen!
Was passiert denn bei?
Code: Alles auswählen
f = Foo(10, 20)
another_foo = Foo(30, 50)
b = Bar(*x, *y, 30)
Der Interpreter müßte ja erst einmal ein Mapping herstellen zwischen Objekten der Oberklasse und denen der Unterklasse. Wenn er das tatsächlich schaffen sollte, so muss er ja noch entscheiden, welche Werte denn jetzt übernommen werden! Und was passiert, wenn ein Objekt gelöscht wird? Verbleiben dann die Werte?
ice2k3 hatte Dir doch quasi eine Lösung dafür angegeben, wie man so etwas durchaus elegant lösen kann, wenn man es mal braucht.
Verfasst: Dienstag 20. Oktober 2009, 13:52
von crs
Seeker hat geschrieben:hm... also muss ich zwingend wieder x und y neu angeben?
Ich kann einfach die "Verarbeitung" von x und y übernehmen, aber die Werte können nicht "vererbt" werden?
die werte von x und y gehören zu einer bestimmten
Instanz der Klasse und werden daher nicht mit vererbt. vererbt werden nur die attribute selbst.
mit dem code von vorhin wuerde daher nur so etwas gehen:
Code: Alles auswählen
In [1]: f = Foo(23, 42)
In [2]: f.x
Out[2]: 23
In [3]: b = Bar(1337, 23, 42)
In [4]: b.x
Out[4]: 23
In [5]: b.z
Out[5]: 1337
Verfasst: Dienstag 20. Oktober 2009, 14:00
von EyDu
Du hast das Prinzip von Klassen wohl noch nicht richtig verstanden. Du kannst beliebig viele Exemplare einer Klasse erstellen. Diese Exemplare haben alle (prinzipiell) keine Ahnung, was in den anderen Exemplaren geschieht.
Mit einer Klasse Fahrzeug kannst du tausende Exemplare eines Fahrzeugs erstellen, kein Fahrzeug weiß aber etwas von den anderen Fahrzeugen. Zum Beispiel, wo diese gerade stehen oder welches Nummernschild sie haben. Ein Exemplar weiß nur wo es selbst steht und welches Nummernschild es selbst hat.
Vererbung kannst du dir dann so vorstellen, dass eine Klasse Auto von Fahrzeug erbt, oder LKW von Fahrzeug erbt. Autos und LKWs sind Fahrzeuge und können deren Eigenschaften Annehmen. Alle Exemplare von Fahrzeug, Auto und LKW kennen aber immer noch nur ihre eigenen Eigenschaften.
Code: Alles auswählen
class Fahrzeug(object):
def __init__(self, nr):
self.nr = nr
class Auto(Fahrzeug):
def __init__(self, nr, sitze):
Fahrzeug.__init__(self, nr)
self.sitze = sitze
class LKW(Fahrzeug):
def __init__(self, nr, laderaum):
Fahrzeug.__init__(self, nr)
self.laderaum = laderaum
f1 = Fahrzeug("F1")
f2 = Fahrzeug("F2")
a1 = Auto("A1", 5)
a2 = Auto("A2", 2)
l1 = LKW("L1", 23)
l2 = LKW("L2", 42)
print f1.nr
print f2.nr
print a1.nr
print a2.nr
print l1.nr
print l2.nr
print a1.sitze
print a2.sitze
print l1.laderaum
print l2.laderaum
Verfasst: Dienstag 20. Oktober 2009, 17:42
von Seeker
Ja, jetzt verstehe ichs =).
Jetzt verstehe ich vor allem den Sinn der Klassen besser. Ich glaube, ich hatte in meinem Kopf noch ein Wirrwarr mit Variabeln der Klasse und Methoden einer Klasse usw.
Bei weiterem Ausprobieren ist mir nun auch noch klar geworden, weshalb meine Idee in der Praxis nicht so viel Sinn macht =P.
Danke an alle =)
lg Seeker