Hallo,
ich wollte mal lernen richtig objektorientiert zu programmieren. Bis jetzt hatte ich immer nur eine Klasse und habe darin dann prozedural programmiert. Leider haben auch alle Beispielcodes, die ich so kenne nur eine Klasse oder sind vieeeeel zu schwer zu verstehen.
Kennt jemand ein leichtes Beispiel, wo mehrere Klassen miteinander agieren und vielleicht ein Objekt mehrere andere Objekte aufnimmt und die vielleicht auch speichert?
Mir fällt da z.B. eine Schule ein:
-3 Klassen (Schüler, Klasse, Schule)
-Schüler mit Name, Alter, Aussehen
-Klasse, die die Schüler beinhaltet und auch eigene Besonderheiten hat (Jahrgang etc.)
-Schule, die die Klassen enthält und auch gespeichert werden kann
Falls dies gespeichert wurde - wie greife ich dann wieder auf einen Schüler zu?
SchuleXY.KlasseXY.Franz.name?
Vielleicht kennt ja jemand etwas, wo man das mal anhand von einfachen Codebeispielen lernen kann.
So long
Carsten
[gelöst] Klassen, die miteinander interagieren
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Dein Ansatz ist doch schon mal nicht schlecht! Allerdings solltest Du Dir auch Funktionalität überlegen die Du in eine Klasse packst. Im Moment nutzt Du die ja stumpf als Datenobjekte (was natürlich an sich nicht verkehrt ist!), aber so lernt man den eigentlich Vorteil bzw. die Besonderheit von Klassen nicht wirklich.
Hast Du das Tutorial mal durchgearbeitet? Dort wird ja auch auf Klassen eingegangen!
Die einfachste Funktionalität könnte es sein, dass sich jede Klasse selber in Textform ausgibt. So braucht die Klasse "Schule" nicht jede einzelne Klasse "Klasse" aufrufen, sondern muss nur über die "Klassen" iterieren und deren "print"-Methode aufrufen.
Also, am besten mal ganz einfach anfangen!
Hast Du das Tutorial mal durchgearbeitet? Dort wird ja auch auf Klassen eingegangen!
Die einfachste Funktionalität könnte es sein, dass sich jede Klasse selber in Textform ausgibt. So braucht die Klasse "Schule" nicht jede einzelne Klasse "Klasse" aufrufen, sondern muss nur über die "Klassen" iterieren und deren "print"-Methode aufrufen.
Also, am besten mal ganz einfach anfangen!
Naja, man kann ja noch Funktionen einbringen. Schüler altern lassen, Auslandsjahr machen lassen oder so... Schule abbrennen (nein, Scherz *g*).Hyperion hat geschrieben:Allerdings solltest Du Dir auch Funktionalität überlegen die Du in eine Klasse packst. Im Moment nutzt Du die ja stumpf als Datenobjekte (was natürlich an sich nicht verkehrt ist!), aber so lernt man den eigentlich Vorteil bzw. die Besonderheit von Klassen nicht wirklich.
Welches meinst du jetzt direkt? Die zwei, die ich schön finde sind (an der Stelle Klassen):Hast Du das Tutorial mal durchgearbeitet? Dort wird ja auch auf Klassen eingegangen!
http://www.ibiblio.org/swaroopch/byteof ... asses.html
und
http://docs.python.org/tut/node11.html
Hier ist aber, wie ich schon anmerkte, immer nur eine Klasse dargestellt und nicht wie diese mit anderen interagiert

Und wie würde sowas gehen? Man braucht doch immer den Instanzname, um etwas spezielles aufzrufen? Genau diese meinte ich, hier hören die Tutorials auf... Vielleicht denke ich aber auch nur zu kompliziert?Die einfachste Funktionalität könnte es sein, dass sich jede Klasse selber in Textform ausgibt. So braucht die Klasse "Schule" nicht jede einzelne Klasse "Klasse" aufrufen, sondern muss nur über die "Klassen" iterieren und deren "print"-Methode aufrufen.
Danke aber für deine Antwort, das mit den Funktionen hat schon zum Nachdenken angeregt
Aber ich hätte halt gern mal ein komplettes Beispiel (mit Klassendefinition, Instanzierung und Benutzen der Instanzen mit Bezugnahme auf andere Instanzen). Es muss ja nicht mein Schulbeispiel sein, das sollte auch eher nur verdeutlichen, was ich meine. Gibt es soetwas denn nicht?
Grüße
Carsten
- Rebecca
- User
- Beiträge: 1662
- Registriert: Freitag 3. Februar 2006, 12:28
- Wohnort: DN, Heimat: HB
- Kontaktdaten:
http://paste.pocoo.org/show/30255/ 
Edit: Das Programm enthaelt einen kleinen Fehler. Der ist natuerlich extra zu Uebungszwecken eingebaut.

Edit: Das Programm enthaelt einen kleinen Fehler. Der ist natuerlich extra zu Uebungszwecken eingebaut.

Offizielles Python-Tutorial (Deutsche Version)
Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Ok, dann mal auf die Schnelle und ungetestet:
Ok, war nicht schnell genug! Obiges Bsp ist natürlich viel schöner 
Code: Alles auswählen
class Student(object):
def __init__(self, name):
self.name = name
def foo(self):
print "Ich bin eine Instanz von Student und mein Name ist", self.name
class Grade(object):
def __init__(self, name):
self.name = name
self.students = []
def foo(self):
print "Ich bin eine Instanz von Grade und mein Name ist", self.name
# Genau das scheint Dir noch unklar zu sein :-)
def printStudents(self):
for i in self.students:
i.foo()
def main():
c = Class("10a")
c.foo()
students = [Student("Peter Müller"), Student("Max Mustermann")]
c.students = students
c.printStudents()

Kleines Beispiel mit Würfeln, das als Grundlage für Yatzee/Kniffel dienen könnte:
http://paste.pocoo.org/show/30260/
http://paste.pocoo.org/show/30260/
hui, gibt es hier viele Antworten 
@Rebecca: danke, sieht sehr übersichtlich aus, aber ich habe auf die Schnelle keinen Fehler finden können. Vielleicht bekomme ich eine Fehlermeldung, wenn ich zuhause teste (bin grad auf Arbeit) *g*
@Hyperion: Ich denke mal es muss in der main-Funktion c = Grade("10a") heißen. Aber ansonsten hast du genau den Punkt getroffen, der mir unklar ist
Eigentlich weiß man ja erst im Programm, wie die jeweilige Instanz heißt, aber wenn man den Namen bei der Initialisierung gleich mit übergibt und einen "internen" Namen gibt, kann man natürlich mit schon "bekannten" Variablen arbeiten, guter Gedanke...
@BlackJack: Ein Würfelbeispiel passt zu deinem Namen
Aber sowas:
wollte ich eigentlich IN der Klasse vermeiden. Habe irgendwann mal gelesen, dass es besser sei immer mit Instanzen zu arbeiten anstatt mit den Objekten direkt? Aber auch ein nettes Beispiel trotzdem...
Wäre es auch guter Programmierstil Instanzen von Klassen in anderen Klassen zu verwenden?
Warum bedarf es für sowas erst einen Forenbeitrag? Können die Tutorials das nicht enthalten? (rhetorische Fragen *g*)
So long und nochmals Danke für eure Hilfe
Carsten
P.S.: Ich teste mal heute oder morgen abend die Beispiele und setze den Thread auf gelöst, wenn ich keine Fragen mehr habe

@Rebecca: danke, sieht sehr übersichtlich aus, aber ich habe auf die Schnelle keinen Fehler finden können. Vielleicht bekomme ich eine Fehlermeldung, wenn ich zuhause teste (bin grad auf Arbeit) *g*
@Hyperion: Ich denke mal es muss in der main-Funktion c = Grade("10a") heißen. Aber ansonsten hast du genau den Punkt getroffen, der mir unklar ist

@BlackJack: Ein Würfelbeispiel passt zu deinem Namen

Aber sowas:
Code: Alles auswählen
self.dices = [Dice(sides) for dummy in xrange(number)]
Wäre es auch guter Programmierstil Instanzen von Klassen in anderen Klassen zu verwenden?
Warum bedarf es für sowas erst einen Forenbeitrag? Können die Tutorials das nicht enthalten? (rhetorische Fragen *g*)
So long und nochmals Danke für eure Hilfe
Carsten
P.S.: Ich teste mal heute oder morgen abend die Beispiele und setze den Thread auf gelöst, wenn ich keine Fragen mehr habe

- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Äh ... ja, natürlichZando hat geschrieben: @Hyperion: Ich denke mal es muss in der main-Funktion c = Grade("10a") heißen. Aber ansonsten hast du genau den Punkt getroffen, der mir unklar ist![]()


Das habe ich nun wieder nicht verstanden?Eigentlich weiß man ja erst im Programm, wie die jeweilige Instanz heißt, aber wenn man den Namen bei der Initialisierung gleich mit übergibt und einen "internen" Namen gibt, kann man natürlich mit schon "bekannten" Variablen arbeiten, guter Gedanke...
Also für mich ist Objekt = Instanz! Liege ich da falsch oder siehst Du das "falsch"? Erbitte da Aufklärung!@BlackJack: Ein Würfelbeispiel passt zu deinem Namen
Aber sowas:wollte ich eigentlich IN der Klasse vermeiden. Habe irgendwann mal gelesen, dass es besser sei immer mit Instanzen zu arbeiten anstatt mit den Objekten direkt? Aber auch ein nettes Beispiel trotzdem...Code: Alles auswählen
self.dices = [Dice(sides) for dummy in xrange(number)]
Also wenn wir bei der Terminologie dieselbe Sprache sprechen (s.o.), dann muss man das sogar tun, wenn man denn mit verschachtelten Klassen arbeiten will! In meinem Beispiel hält das Attribut students eben eine Liste von Instanzen der Klasse Student. Prinzipiell wird eine Vernestelung immer auf diese Weise erreicht (neben Listen eben auch durch andere Container).Wäre es auch guter Programmierstil Instanzen von Klassen in anderen Klassen zu verwenden?
Tja, schreib doch einfach selber eines von einem Anfänger für Anfänger! Ich bin nicht mit Python groß geworden, daher war mir von vornherein einiges "klar", was bei anderen Vorkenntnissen evtl. halt zu Problemen geführt haben könnte. Insofern ist es natürlich auch schwer ein Tutorial so zu schreiben, dass es jeder versteht - wenn das so leicht ginge, wären wir alle Theoretische PhysikerWarum bedarf es für sowas erst einen Forenbeitrag? Können die Tutorials das nicht enthalten? (rhetorische Fragen *g*)

@Zando: Man könnte die einzelnen Würfel in einem `Dices`-Objekt auch von aussen "zuführen", oder der `Dices.__init__()` ein Argument hinzufügen, so dass die Würfel zwar in der Methode erzeugt werden, aber der Benutzer der Klasse selbst bestimmen kann, wie so ein Würfel aussieht, wenn er denn möchte:
Das kommt aber letztendlich immer auf den Verwendungszweck an. Wenn der Benutzer der Würfel eh nur mit `Dices`-Objekten konfrontiert werden soll, dann ist `Dice` ein Implementierungsdetail, was er nicht kennen muss und alles andere zu komplex.
Man sollte auf jeden Fall vermeiden Quelltext von vornherein zu flexibel zu schreiben. Er sollte natürlich schon flexibel sein, aber wenn man zu viel abstrahiert, hat man hinterher viel komplexeren Code, den man gar nicht benötigt.
Die Änderung da oben kann man zum Beispiel immer noch nachträglich machen, ohne das sich die API für bestehenden Quelltext ändert.
Man sollte keinen Code schreiben, den man so nicht benötigt. Darum der Rat von Hyperion gleich in der ersten Antwort, dass Du Dir Gedanken über die Funktionalität machen sollst. Alles was für die geplante Funktionalität nicht benötigt wird, ist toter Ballast, der den Quelltext länger macht und Fehler enthalten kann.
"Test driven development" (TDD) kann da hilfreich sein. Man macht sich Gedanken über die Funktionalität, also was will ich mit den Objekten machen. Dann schreibt man einen Test. Dann den Code, damit dieser Test korrekt läuft. Dann den nächsten Test und danach den Code dazu, und so weiter.
Code: Alles auswählen
def __init__(self, number=5, sides=6, dice_factory=Dice):
self.dices = [dice_factory(sides) for dummy in xrange(number)]
Man sollte auf jeden Fall vermeiden Quelltext von vornherein zu flexibel zu schreiben. Er sollte natürlich schon flexibel sein, aber wenn man zu viel abstrahiert, hat man hinterher viel komplexeren Code, den man gar nicht benötigt.
Die Änderung da oben kann man zum Beispiel immer noch nachträglich machen, ohne das sich die API für bestehenden Quelltext ändert.
Man sollte keinen Code schreiben, den man so nicht benötigt. Darum der Rat von Hyperion gleich in der ersten Antwort, dass Du Dir Gedanken über die Funktionalität machen sollst. Alles was für die geplante Funktionalität nicht benötigt wird, ist toter Ballast, der den Quelltext länger macht und Fehler enthalten kann.
"Test driven development" (TDD) kann da hilfreich sein. Man macht sich Gedanken über die Funktionalität, also was will ich mit den Objekten machen. Dann schreibt man einen Test. Dann den Code, damit dieser Test korrekt läuft. Dann den nächsten Test und danach den Code dazu, und so weiter.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Interessanter Ansatz - kannte ich noch nicht. Muss mich da mal schlau lesen!BlackJack hat geschrieben: "Test driven development" (TDD) kann da hilfreich sein. Man macht sich Gedanken über die Funktionalität, also was will ich mit den Objekten machen. Dann schreibt man einen Test. Dann den Code, damit dieser Test korrekt läuft. Dann den nächsten Test und danach den Code dazu, und so weiter.
egal, ich schon. Da habe ich schon weitergedacht, wie es ist, wenn man mal die Namen der Instanzen bei der Programmierung noch nicht kennen sollteHyperion hat geschrieben:Das habe ich nun wieder nicht verstanden?Zando hat geschrieben: Eigentlich weiß man ja erst im Programm, wie die jeweilige Instanz heißt, aber wenn man den Namen bei der Initialisierung gleich mit übergibt und einen "internen" Namen gibt, kann man natürlich mit schon "bekannten" Variablen arbeiten, guter Gedanke...

Kommando zurück, es wird ja hier auch eine Liste generiert. Und die Worte Objekt und Klasse hab ich auch verwechselt@BlackJack: Ein Würfelbeispiel passt zu deinem Namen
Aber sowas:wollte ich eigentlich IN der Klasse vermeiden. Habe irgendwann mal gelesen, dass es besser sei immer mit Instanzen zu arbeiten anstatt mit den Objekten direkt? Aber auch ein nettes Beispiel trotzdem...Code: Alles auswählen
self.dices = [Dice(sides) for dummy in xrange(number)]
Also für mich ist Objekt = Instanz! Liege ich da falsch oder siehst Du das "falsch"? Erbitte da Aufklärung!

Ok, danke, das wollte ich nur wissen...Also wenn wir bei der Terminologie dieselbe Sprache sprechen (s.o.), dann muss man das sogar tun, wenn man denn mit verschachtelten Klassen arbeiten will! In meinem Beispiel hält das Attribut students eben eine Liste von Instanzen der Klasse Student.
Und ich habe "immer" (immer mal) nur prozedural programmiert und mit Basic auf dem C64 angefangenTja, schreib doch einfach selber eines von einem Anfänger für Anfänger! Ich bin nicht mit Python groß geworden, daher war mir von vornherein einiges "klar", was bei anderen Vorkenntnissen evtl. halt zu Problemen geführt haben könnte.

Daher ist es schwierig sich da reinzudenken. Sieht man ja schon bei der Benamsung (Instanz, Klasse) und eben dem Zusammenspiel von Klassen, was ja hier schön rübergekommen ist...
Und zum Selberschreiben: ich habe ja schon ein paar Tutorials gelesen und die Grundlagen kommen gut rüber, aber Klassen werden halt immer sehr kurz behandelt (eh ich mal "self" verstanden habe, gingen auch viele Sonnen unter

So long
Carsten
Genau das meinte ich mit nicht IN der Klasse direkt, da ich immer sehr darauf achte, dass etwas flexibel ist. Vielleicht sollte ich mich davon etwas lösen. Und das es Instanzen sind, habe ich ja im vorigen Post schon zugegebenBlackJack hat geschrieben: Das kommt aber letztendlich immer auf den Verwendungszweck an. Wenn der Benutzer der Würfel eh nur mit `Dices`-Objekten konfrontiert werden soll, dann ist `Dice` ein Implementierungsdetail, was er nicht kennen muss und alles andere zu komplex.
Man sollte auf jeden Fall vermeiden Quelltext von vornherein zu flexibel zu schreiben. Er sollte natürlich schon flexibel sein, aber wenn man zu viel abstrahiert, hat man hinterher viel komplexeren Code, den man gar nicht benötigt.

So long
Carsten
Z.B. hier: diveintopythonHyperion hat geschrieben:Interessanter Ansatz - kannte ich noch nicht. Muss mich da mal schlau lesen!BlackJack hat geschrieben: "Test driven development" (TDD) kann da hilfreich sein. Man macht sich Gedanken über die Funktionalität, also was will ich mit den Objekten machen. Dann schreibt man einen Test. Dann den Code, damit dieser Test korrekt läuft. Dann den nächsten Test und danach den Code dazu, und so weiter.
Habe jetzt gerade Testgetriebene Entwicklung mit JUnit & FIT gelesen. Ist zwar für Java, von dem ich eigentlich keine Ahnung habe, kann man aber auch gut für Python verwenden. Für die Software-Entwicklung im professionellen Bereich finde ich den Ansatz gut, für den Home-User eher übertrieben und auch kaum in der Konsequenz umsetzbar.
MfG
HWK
Also ich konnte gestern abend keinen Fehler entdecken. Lief ohne zu meckern das Programm...Rebecca hat geschrieben:http://paste.pocoo.org/show/30255/
Edit: Das Programm enthaelt einen kleinen Fehler. Der ist natuerlich extra zu Uebungszwecken eingebaut.
So long
Carsten
edit: Noch eine Frage so allgemein: sollte man das "object" bei einer Klassendefinition mit angeben?
Also "Klasse(object):" anstatt "Klasse:"?
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Kommt drauf an: Stichwort new-style-classes!Zando hat geschrieben:Rebecca hat geschrieben: edit: Noch eine Frage so allgemein: sollte man das "object" bei einer Klassendefinition mit angeben?
Also "Klasse(object):" anstatt "Klasse:"?
[wiki]New-Style Klassen[/wiki]?highlight=%28klasse%29
Die Antwort war mir gestern klarer, da ich meine Frage wieder unpräzise gestellt habe und die Antwort ja gepasst hatHyperion hat geschrieben:Also wenn wir bei der Terminologie dieselbe Sprache sprechen (s.o.), dann muss man das sogar tun, wenn man denn mit verschachtelten Klassen arbeiten will! In meinem Beispiel hält das Attribut students eben eine Liste von Instanzen der Klasse Student. Prinzipiell wird eine Vernestelung immer auf diese Weise erreicht (neben Listen eben auch durch andere Container).Zando hat geschrieben: Wäre es auch guter Programmierstil Instanzen von Klassen in anderen Klassen zu verwenden?

Ich meinte eher: Wäre es guter Programmierstil die Instanzen auch in den anderen Klassen zu erzeugen? Ihr (Rebecca und du) erzeugt die Instanzen ja außerhalb der Klassen (anderen Instanzen?), während BlackJack sie innerhalb erzeugt.
Falls ich wieder sprachliche Probleme habe, hier ein Beispiel:
"ihr" macht es so:
Code: Alles auswählen
class Erste:
pass
class Zweite:
def __init__(self, wasvomersten):
blablablub...
ausserhalb = Erste()
zweite = Zweite(ausserhalb)
Code: Alles auswählen
class Erste:
pass
class Zweite:
def __init__(self):
self.innerhalb = Erste()

BlackJacks Lösung ist eher dafür falls alle Zweite-Objekte(Instanzen) DASGLEICHE Erste-Objekt enthalten sollen und "eure" eher falls es verschiedene Erste-Objekte gibt, die in den verschiedenen Zweite-Objekten verwendet werden sollen?
So long
Carsten
edit: vor "innerhalb" im Quellcode noch ein "self" gesetzt...
Zuletzt geändert von Zando am Donnerstag 28. Februar 2008, 11:16, insgesamt 1-mal geändert.
Kommt drauf anHyperion hat geschrieben:Kommt drauf an: Stichwort new-style-classes!Zando hat geschrieben:
[wiki]New-Style Klassen[/wiki]?highlight=%28klasse%29

So long
Carsten
- Rebecca
- User
- Beiträge: 1662
- Registriert: Freitag 3. Februar 2006, 12:28
- Wohnort: DN, Heimat: HB
- Kontaktdaten:
Nein, die __init__-Methode wird ja bei jedem Mal aufgerufen, wenn eine neue Instanz erzeugt wird. Also wird in BlackJacks fall bei jedem Erzeugen einer Zweite-Instanz auch eine neue Erste-Instanz erzeugt.Zando hat geschrieben:Ok, ist mir während des Schreibens klarer geworden
BlackJacks Lösung ist eher dafür falls alle Zweite-Objekte(Instanzen) DASGLEICHE Erste-Objekt enthalten sollen und "eure" eher falls es verschiedene Erste-Objekte gibt, die in den verschiedenen Zweite-Objekten verwendet werden sollen?
Der Unterschiede ist einfach der, dass bei BlackJacks halt "irgendeine" Erste-Instanz erzeugt wird, der Benutzer der Zweite-Klasse hat darauf keinen Einfluss. In meinen Fall kann der Benutzer der Zweite-Klasse genau entscheiden, welche Erzte-Instanz in der Zweite-Instanz vorhanden sein soll. Das macht in der Schulklassen-Klasse ja auch sinn: Es sind ganz bestimmte Schueler in der Klasse (Max Mustermann, Helga Hampel,...), nicht irgendwelche Standard-Schueler.
Offizielles Python-Tutorial (Deutsche Version)
Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
@Rebecca: ich könnte mich jetzt rausreden und sagen, das mit dasgleiche ja unterschiedliche gemeint sind und nicht dasselbe. Aber da hab ich in dem Moment gar nicht so dran gedacht. Im Endeffekt ist es aber so wie ich es mir dachte.
Mit dem Einfluss drauf haben, ist es vielleicht noch etwas besser beschrieben, danke *g*
So long
Carsten
Mit dem Einfluss drauf haben, ist es vielleicht noch etwas besser beschrieben, danke *g*
So long
Carsten
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Naja, im Endeffekt ist es gar nicht so verschieden, wenn man an ein komplexes Programm denkt. Dort wirst Du sicherlich Klassen haben, innerhalb deren andere Instanzen erzeugt werden. Ob das nun aus einer Funktion heraus geschieht oder eben aus einer Klasse bzw einer ihrer Methoden macht imho keinen großen Unterschied 
