Beispiel für OOP Version 2

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.
Antworten
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

Hallo zusammen,

in den verschiedenstens Tutorials gibt es Bsp. zum Thema OOP.
Die meisten Beispiele sind aber meiner Meinung nach sehr sinnlos.

Ich finde folgendes Beispiel für die Einführung in diese Thematik sehr gelungen:

Einiges habe ich inzwischen ausgebessert. Ich hoffe alle Termini sind jetzt korrekt.

Code: Alles auswählen

#!/usr/bin/python

class GehaltsKonto:

    HabenZins=0,5
    SollZins=6

    def __init__(self, Nachname, Vorname, Kontonummer, Kontostand=0):

        self.Nachname=Nachname
        self.Vorname=Vorname
        self.Kontonummer=Kontonummer
        self.Kontostand=Kontostand


    def einzahlen(self):
        pass

    def auszahlen(self):
        pass

    def ueberweisen(self):
        pass

    def kontostand_ausgeben(self):
        pass

    def quartal_berechnen(self):
        pass


if __name__=='__main__':

    konto1=GehaltsKonto("Mair", "Sepp", 123456)
    konto2=GehaltsKonto("Hofer", "Maria", 234567)
Der eigentliche Nutzen von OOP: die Definition von eigenen Datentypen.

Praktisch dabei ist, dass wir beliebig viele Objekte, bzw. Instanzen eines definierten Datentyp erzeugen können.

Die aufgenommenen Daten können manipuliert werden. Dazu stehen uns Methoden (Funktionen) zur Verfügung.

Der Unterschied zwischen Klassen und Instanzattribute lässt sich hier gut erklären:
Klassenattribute gelten für alle Instanzen bzw. Objekte, die wir ableiten. Eine Instanz, Objekt ist ein konkretes Abbild einer Datentypdefinition.
Jedes erzeugte Objekt, kann bei seiner Entstehung (__init__) mit Werten gefüttert werden. Es gibt aber auch Werte die für alle Objekte gelten. Ganz egal wie man heisst, welche Kontonummer jmd. hat, für ein Gehaltskonto gelten immer die gleichen Zinssätze.

Die Methoden zur Manipulation wurden nur skizziert, daher immer die Anweisung pass.


Nun möchte ich gern wissen, wie euch das Beispiel gefällt?

Liebe Grüße

rolgal_reloaded
Zuletzt geändert von rolgal_reloaded am Mittwoch 25. Oktober 2006, 11:30, insgesamt 2-mal geändert.
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Mir wuerde

Code: Alles auswählen

konto1 = GehaltsKonto("Rebecca", "Breu", 123456)
besser gefallen. :wink:

Das Beispiel fuer die statischen Variablen finde ich gut. einzahlen und auszahlen sind nur setter fuer KStand und somit ueberfluessig.

Ach ja, und man macht Leerzeichen um Operatoren (wie zum Beispiel '=').
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

Die Methoden zur Manipulation wurden nur skizziert, daher immer die Anweisung pass.
mit pass kann ich mich noch anfreunden, aber wenigstens die signatur sollte gegeben sein, um missverständnissen vorzubeugen, also

Code: Alles auswählen

class GehaltsKonto:
    # [...]
    def einzahlen(self, amount):
        pass
    # [...]
oder, wenn man wirklich faul sein will, allen methoden die signatur

Code: Alles auswählen

def method(self, *args, **kwargs):
  pass
geben.
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

Hallo Rebecca,

wenn man was einzahlt, dann ändert sich KStand und das sollte doch nur über eine definierte Schnittstelle passieren, oder meinst du was anderes?

Was dir an deinem Instanzaufruf besser gefällt ist mir auch nicht klar.

Die Leerzeichen sind doch nicht zwingend bei '=' . Warum findest du sie so wichtig?

Liebe Grüße

rolgal_reloaded
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

Hallo keppla,

es ging in dem Beispiel nur um die Erklärung von dem Prinzip der OOP. Ich lasse dann gern alles, was weitere Fragen aufwerfen könnte zunächst weg.

Bez. Signatur stehe ich auf der Leitung :?:

Hilf mir mal weiter, danke.

LG

rolgal
BlackJack

rolgal_reloaded hat geschrieben:in den verschiedenstens Tutorials gibt es Bsp. zum Thema OOP.
Die meisten Beispiele sind aber meiner Meinung nach sehr sinnlos.
Was hauptsächlich daran liegen dürfte, dass OOP ein Mittel ist um Komplexität in den Griff zu bekommen. Folglich ist es schwer einfache, sinnvolle Beispiele zu finden bei denen es ja keine Komplexität zu bändigen gibt, sonst wären sie nicht einfach. :-)

Das war mein Problem als uns der Informatik-Lehrer damals in der Schule OOP als kleines Extra am Jahresende beibringen wollte. Er hat Ansatzweise angefangen die einfache Anwendung die wir im Laufe des Schuljahres geschrieben hatten, in OO umzuschreiben und wir sassen nur da und dachten, okay das Programm macht immer noch das gleiche, aber mit viel mehr Zeilen Code und so komischen Objekten -- was soll das!? Da hat die Objektorientierung mehr Komplexität erzeugt als sie beseitigt hat.
Ich finde folgendes Beispiel für die Einführung in diese Thematik sehr gelungen:
Namensgebung ist nicht PEP8 konform und mir sind da zuviele Abkürzungen. Beim lesen kurz gestutzt habe ich bei `HZI-ns`, das Minus habe ich an der Stelle eingefügt wo bei mir in Gedanken zuerst die "Bruchstelle" war bevor ich realisiert habe das es `H-ZIns` ist.

Aber was spricht gegen `haben_zinssatz` statt `HZIns` oder `vorname` statt `VName` oder `kundennummer` statt `KNummer`, ups das war wohl eher `kontonummer`.

Das meiste bekommt man irgendwie dann doch mit, aber bei `qu_berechnen` streikt meine Vorstellungskraft.

Ob Kontonummern Zahlen sind, wäre übrigens eine Diskussion Wert. Bei Bankleitzahlen würde ich die Frage zum Beispiel definitiv verneinen.
Der eigentliche Nutzen von OOP: die Definition von eigenen Datentypen.
Abstrakte Datentypen inklusive Operationen. Nur Datentypen gibt's auch ohne OOP. ``Record`` in Pascal, ``struct`` in C und ``Type`` in QuickBasic zum Beispiel.
Praktisch dabei ist, dass wir beliebig viele Datentypen dieser Definiton erzeugen können.
Hier und im folgenden benutzt Du das Wort "Datentypen" falsch. Es werden Objekte von dem definierten Datentyp erzeugt und keine neuen Datentypen.
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

Hallo BlackJack,


du hast natürlich Recht. Objekte eines definierten Datentyps werden erzeugt.
Wollte ich eigentlich auch so verstanden wissen. Dann hätte ich es auch so schreiben sollen (nona
:D )

Namensgebung: PEP8 ? :shock:
Bitte um Aufklärung.

Ich werde die Abkürzungen rausschmeissen, hast eigentlich recht. Ich mag nur elendslange Bezeichnungen eigentlich nicht, aber wenn ein Anfänger vor dem Code sitzt und ich ihn mit Abkürzungen verwirre, dann ist das didaktischer Unfug.

qu_berechnen: sollte heissen: Quartal_berechnen. Hier kämen dann z.b. die Zinssätze zum tragen. War mal so die Idee.

Liebe Grüße

rolgal
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

Hallo BlackJack,

sei mal so nett und lies die Erklärung nochmal durch, ob jetzt alle Begriffe korrekt sind.

Vielen Dank

rolgal
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

rolgal_reloaded hat geschrieben:es ging in dem Beispiel nur um die Erklärung von dem Prinzip der OOP. Ich lasse dann gern alles, was weitere Fragen aufwerfen könnte zunächst weg.
Bez. Signatur stehe ich auf der Leitung :?:
Mit Signatur meinte ich allgemein folgendes: http://de.wikipedia.org/wiki/Signatur_% ... mierung%29

und im speziellen, dass eine methode einzahlen() keinen Sinn hat, da man nicht angeben kann, wieviel man einzahlt. Hat zwar nicht primär was mit OOP zu tun, würde mich aber doch verwirren, wenn ich versuche, es nachzuvollziehen (was genau soll denn einzahlen() bewirken?), und es so eventuell mehr schaden als nutzen würde, hier nichts zu schreiben.

besser wäre, wenn da

Code: Alles auswählen

def einzahlen(self, betrag): pass
stünde, weil dann klar wäre, dass die Methode so genutzt werden könnte:

Code: Alles auswählen

meinkonto.einzahlen(20.0)

Code: Alles auswählen

def method(self, **args, **kwargs): pass
Ist einfach nur eine Methode, die gar keine Aussage über das trifft, was sie an Argumenten nimmt, im Gegensatz zu

Code: Alles auswählen

def method(self):pass
, die exakt null Argumente nimmt.
Benutzeravatar
Matflasch
User
Beiträge: 41
Registriert: Donnerstag 25. März 2004, 15:42
Wohnort: Hamburg
Kontaktdaten:

Da muss ich auch gleich mal was fragen...
Ich komme aus (und bleibe in) der Java-Welt (gezungenermaßen ;))
Generell sind die Klassenattribute private/protected und nur über get-/set-Methoden anzusprechen...

Wie sieht es da genau in Python aus?

Code: Alles auswählen

def __init__(self, Nachname, Vorname, Kontonummer, Kontostand=0):
    self.Nachname=Nachname
    self.Vorname=Vorname
    self.Kontonummer=Kontonummer
    self.Kontostand=Kontostand 
So ist es für "Manipulation" ja relativ offen.
Aber:

Code: Alles auswählen

def __init__(self, Nachname, Vorname, Kontonummer, Kontostand=0):
    self._Nachname=Nachname
    self._Vorname=Vorname
    self._Kontonummer=Kontonummer
    self._Kontostand=Kontostand 
Oder...

Code: Alles auswählen

def __init__(self, Nachname, Vorname, Kontonummer, Kontostand=0):
    self.__Nachname=Nachname
    self.__Vorname=Vorname
    self.__Kontonummer=Kontonummer
    self.__Kontostand=Kontostand 
Wie "sollte" es gemacht werden?
Ich meine, dass ich letztes im PEP8 in etwa gelesen habe: "Wir sind alle Erwachsene Leute, daher getter/setter weglassen und nutzen" ;)

Aber wie sieht es dann mit dem Schutz aus?
Das ist eine Sache, bei der ich mir in Python nicht wirklich sicher bin, wie man es am besten benutzen könnte.
Angenommen, man will etwas von dem Konto abheben und setzt einfach den Kontostand neu, dann entsteht ja kein dazugehöriger "Buchungssatz", der z.B. durch eine set-Methode protokolliert werden könnte...

Ich glaub ich denke noch zu typisiert :?
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

Matflasch hat geschrieben:Da muss ich auch gleich mal was fragen...
Ich komme aus (und bleibe in) der Java-Welt (gezungenermaßen ;))
Generell sind die Klassenattribute private/protected und nur über get-/set-Methoden anzusprechen...
Wie sieht es da genau in Python aus?
In Python wird das afaik so gesehen:
Private ist kein Schutz vor bösen Einbrechern oder eine Sicherheitsmaßnahme, sondern ein Schutz für Programmierer vor sich selbst, also eher ein Implementationshinweis ("finger wech").
Wenn der Programmierer einer Klasse also etwas nicht erwähnen, fasst man es besser nicht an.
ein führender Unterstrich ist eine Konvention, die besagt, dass es sich um etwas handelt, was vage javas "protected" ist, ein doppelter unterstrich führt dazu, dass dem Namen der Klassenname vorangestellt wird, um versehentliches überscheiben zu verhindern.

Code: Alles auswählen

class A:
  def __xxx(self):
    print 'hello'

a = A()
a._A__xxx()
Wie "sollte" es gemacht werden?
Ich meine, dass ich letztes im PEP8 in etwa gelesen habe: "Wir sind alle Erwachsene Leute, daher getter/setter weglassen und nutzen" ;)
Aber wie sieht es dann mit dem Schutz aus?
Das ist eine Sache, bei der ich mir in Python nicht wirklich sicher bin, wie man es am besten benutzen könnte.
Angenommen, man will etwas von dem Konto abheben und setzt einfach den Kontostand neu, dann entsteht ja kein dazugehöriger "Buchungssatz", der z.B. durch eine set-Methode protokolliert werden könnte...
dazu nutzt du dann properties:

Code: Alles auswählen

def Konto(object):
  def __init__(self):
    self.transactions = []
    self.amount = 0
  def setKontostand(self, amount):
    self.transactions.append( self.amount - amount )
    self.amount = amount
  def getKontotstand(self):
    return self,amount
  kontostand = property(getKontostand, setKontostand)
[/quote]
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Hi, also wenne es sich nur um eine zahl oder sonstwas handelt die sich nicht aus einer erforderlichen Berechnung zusammensetzt = weg mit setter und getter ;)

Wenn es aber anderes ist = setter gettert bzw. property nutzen

BlackJack hat dazu was geschrieben was mir für das Verständnis von Pythons OO half, da ich eher von C++ kam (ganz früher) und es da ja halt mit protected, private etc drum geht und ich der Meinung wahr das es so sein muss und nicht anders ^^

hier der Link zu dem Thread: http://www.python-forum.de/topic-7276.html
Benutzeravatar
Matflasch
User
Beiträge: 41
Registriert: Donnerstag 25. März 2004, 15:42
Wohnort: Hamburg
Kontaktdaten:

XtraNine: Danke, werde ich mir gleich mal durchlesen, denn mir gehts ähnlich ;)

keppla: Danke!
Hat mir schon sehr weiter geholfen.
Habe grad mal ein wenig getestet und bin grad bei dem Resultat stehen geblieben:

Code: Alles auswählen

class Konto(object):
    def __init__(self):
        self.transactions = []
        self._amount = 0
        
    def _setKontostand(self, amount):
        self.transactions.append(self._amount - amount)
        self._amount = amount
        
    def _getKontostand(self):
        return self._amount

    kontostand = property(_getKontostand, _setKontostand)
Einen Unterstrich habe ich nun als "Warnung" mit reingenommen. Das mit property finde ich aber sehr Klasse!
Zugreifen kann man nun auf _amount immernoch, aber das bleibt dem Programmierer dann selbst überlassen, ob er es richtig macht oder machen will, richtig? ;)

Danke soweit!
rolgal_reloaded
User
Beiträge: 312
Registriert: Dienstag 24. Oktober 2006, 19:31

@Keppla,

Hallo,
und im speziellen, dass eine methode einzahlen() keinen Sinn hat, da man nicht angeben kann, wieviel man einzahlt. Hat zwar nicht primär was mit OOP zu tun, würde mich aber doch verwirren, wenn ich versuche, es nachzuvollziehen (was genau soll denn einzahlen() bewirken?), und es so eventuell mehr schaden als nutzen würde, hier nichts zu schreiben.
Ich kann deine Argumentation bez. der Funktionen, Methoden sehr gut nachvollziehen. Du hast fachlich recht und es ist auch didaktisch sinnvoll :!:

Danke! Werde das bald ändern.

@alle anderen.

Freue mich, dass das Beispiel jetzt noch einiges an Gesprächen ausgelöst hat.

Liebe Grüße

rolgal_reloaded
Antworten