[gelöst] Klassen, die miteinander interagieren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Zando
User
Beiträge: 37
Registriert: Sonntag 9. Juli 2006, 17:18

Mittwoch 27. Februar 2008, 11:30

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
Zuletzt geändert von Zando am Donnerstag 28. Februar 2008, 10:43, insgesamt 2-mal geändert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Mittwoch 27. Februar 2008, 12:00

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!
Zando
User
Beiträge: 37
Registriert: Sonntag 9. Juli 2006, 17:18

Mittwoch 27. Februar 2008, 12:31

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.
Naja, man kann ja noch Funktionen einbringen. Schüler altern lassen, Auslandsjahr machen lassen oder so... Schule abbrennen (nein, Scherz *g*).
Hast Du das Tutorial mal durchgearbeitet? Dort wird ja auch auf Klassen eingegangen!
Welches meinst du jetzt direkt? Die zwei, die ich schön finde sind (an der Stelle Klassen):
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 :(
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.
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?

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
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Mittwoch 27. Februar 2008, 12:57

http://paste.pocoo.org/show/30255/ :)

Edit: Das Programm enthaelt einen kleinen Fehler. Der ist natuerlich extra zu Uebungszwecken eingebaut. :wink:
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Mittwoch 27. Februar 2008, 13:02

Ok, dann mal auf die Schnelle und ungetestet:

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()
Ok, war nicht schnell genug! Obiges Bsp ist natürlich viel schöner :-)
BlackJack

Mittwoch 27. Februar 2008, 13:16

Kleines Beispiel mit Würfeln, das als Grundlage für Yatzee/Kniffel dienen könnte:
http://paste.pocoo.org/show/30260/
Zando
User
Beiträge: 37
Registriert: Sonntag 9. Juli 2006, 17:18

Mittwoch 27. Februar 2008, 13:50

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 :D
Aber sowas:

Code: Alles auswählen

self.dices = [Dice(sides) for dummy in xrange(number)]
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 :)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Mittwoch 27. Februar 2008, 14:12

Zando 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 ;)
Äh ... ja, natürlich ;-) Das deutsche Wort Klasse ist in dieser Thematik leider doppelt belegt :-D
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...
Das habe ich nun wieder nicht verstanden?
@BlackJack: Ein Würfelbeispiel passt zu deinem Namen :D
Aber sowas:

Code: Alles auswählen

self.dices = [Dice(sides) for dummy in xrange(number)]
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...
Also für mich ist Objekt = Instanz! Liege ich da falsch oder siehst Du das "falsch"? Erbitte da Aufklärung!
Wäre es auch guter Programmierstil Instanzen von Klassen in anderen Klassen zu verwenden?
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).
Warum bedarf es für sowas erst einen Forenbeitrag? Können die Tutorials das nicht enthalten? (rhetorische Fragen *g*)
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 Physiker :-D
BlackJack

Mittwoch 27. Februar 2008, 14:46

@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:

Code: Alles auswählen

    def __init__(self, number=5, sides=6, dice_factory=Dice):
        self.dices = [dice_factory(sides) for dummy in xrange(number)]
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.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Mittwoch 27. Februar 2008, 14:53

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.
Interessanter Ansatz - kannte ich noch nicht. Muss mich da mal schlau lesen!
Zando
User
Beiträge: 37
Registriert: Sonntag 9. Juli 2006, 17:18

Mittwoch 27. Februar 2008, 14:59

Hyperion hat geschrieben:
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...
Das habe ich nun wieder nicht verstanden?
egal, ich schon. Da habe ich schon weitergedacht, wie es ist, wenn man mal die Namen der Instanzen bei der Programmierung noch nicht kennen sollte ;)
@BlackJack: Ein Würfelbeispiel passt zu deinem Namen :D
Aber sowas:

Code: Alles auswählen

self.dices = [Dice(sides) for dummy in xrange(number)]
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...

Also für mich ist Objekt = Instanz! Liege ich da falsch oder siehst Du das "falsch"? Erbitte da Aufklärung!
Kommando zurück, es wird ja hier auch eine Liste generiert. Und die Worte Objekt und Klasse hab ich auch verwechselt :oops:
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.
Ok, danke, das wollte ich nur wissen...
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.
Und ich habe "immer" (immer mal) nur prozedural programmiert und mit Basic auf dem C64 angefangen :D
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
Zando
User
Beiträge: 37
Registriert: Sonntag 9. Juli 2006, 17:18

Mittwoch 27. Februar 2008, 15:03

BlackJack 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.
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 zugegeben ;)

So long
Carsten
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Mittwoch 27. Februar 2008, 15:18

Hyperion hat geschrieben:
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.
Interessanter Ansatz - kannte ich noch nicht. Muss mich da mal schlau lesen!
Z.B. hier: diveintopython
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
Zando
User
Beiträge: 37
Registriert: Sonntag 9. Juli 2006, 17:18

Donnerstag 28. Februar 2008, 09:52

Rebecca hat geschrieben:http://paste.pocoo.org/show/30255/ :)

Edit: Das Programm enthaelt einen kleinen Fehler. Der ist natuerlich extra zu Uebungszwecken eingebaut. :wink:
Also ich konnte gestern abend keinen Fehler entdecken. Lief ohne zu meckern das Programm...

So long
Carsten

edit: Noch eine Frage so allgemein: sollte man das "object" bei einer Klassendefinition mit angeben?

Also "Klasse(object):" anstatt "Klasse:"?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Donnerstag 28. Februar 2008, 10:23

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:"?
Kommt drauf an: Stichwort new-style-classes!
[wiki]New-Style Klassen[/wiki]?highlight=%28klasse%29
Antworten