Seite 1 von 1

Klassen

Verfasst: Freitag 4. Dezember 2015, 16:45
von BMTP
Hey liebe Python-Master,
also wir haben heute nur kurz das Thema Klassen angefangen, allerdings schon eine Aufgabe dazu gestellt gekriegt, die folgerndermaßen aussieht:
1. Erstellt eine Klasse Person mit den Attributen vorname, nachname, geschlecht und alter
2. die Klasse hat die Methode getGrussformel(), für erwachsene Männer "Sehr geehrter Herr <vorname> <nachname>"
für erwachsene Frauen "Sehr geehre Frau <vorname> <nachname>"
und für Personen unter 18 Jahren " Hallo <vorname>"
zurückgeliefert.

Am Ende des Programms waren folgende Angaben gemacht:

Code: Alles auswählen

a = Person ("Ina", "Schmidt", "W", 18)
b = Person ("Peter", "Meier", "M", 32)
c = Person ("Jan", "Huber", "M", 12)
d = Person ("Lisa", "Maler", "W", 17)

print(a.getGrussformel())
print(b.getGrussformel())
print(c.getGrussformel())
print(d.getGrussformel())
Am Ende sollten also die Personen a-d jeweils mit der Grussformel ausgegeben werden.
Um die Aufgabe zu lösen, habe ich folgenden Code erstellt:

Code: Alles auswählen

class Person(object):
    def __init__(self, vorname, nachname, geschlecht, alter):
        self.vorname = vorname
        self.nachname = nachname
        self.geschlecht = geschlecht
        self.alter = alter

    def getGrussformel(self, vorname, nachname):
        if self.geschlecht == "M" and self.alter > 18:
            getGrussformel = ("Sehr geehrter Herr ",vorname,nachname)


        elif self.alter < 18 :
            getGrussformel = "Hallo "


        else:
            getGrussformel = "Sehr geehrte Frau "
Nun bekomme ich immer einen Error fehler:
TypeError: getGrussformel() missing 2 required positional arguments: 'vorname' and 'nachname'

Wenn ich bei def getGrussformel versucht habe vorname und nachname wegzulassen, gab es zwar keinen fehler, aber hat nur viermal None ausgespuckt. Welche Angaben muss ich also noch machen, um das zu lösen? Ich hoffe ich konnte mein Problem eindeutig erläutern.

Re: Klassen

Verfasst: Freitag 4. Dezember 2015, 16:54
von BlackJack
@BMTP: Die Fehlermeldung ist doch einleuchtend, schliesslich übergibst Du der Methode beim Aufruf weder Vor- noch Nachname. Genau wie Alter und Geschlecht kennt das Objekt diese bereits, man muss halt nur über das Objekt darauf zugreifen. So wie Du das bei Alter und Geschlecht ja auch machst.

`None` wird ausgegeben weil die Methode bei Dir keinen Rückgabewert hat. Das ist Python und kein Pascal. Um Werte zurückzugeben gibt es ein Schlüsselwort. Eine lokale Variable mit dem gleichen Namen wie die Funktion oder Methode zu verwenden macht keinen Sinn, im Gegenteil so etwas ist eher verwirrend und würde auch bei rekursiven Funktionen/Methoden einen rekursiven Aufruf verhindern.

Edit: Die Abfragen/Entscheidungen sind in einer eher ungünstigen Reihenfolge angeordnet, das geht ohne das Alter zweimal zu prüfen. Und man sollte das Geschlecht dann vielleicht auch explizit auf 'M' und 'W' prüfen und auch den Fall behandeln wenn es weder 'M' noch 'W' ist. Es gibt sowohl Programmierfehler als auch Leute die diese Angabe anders beantworten oder gar nicht beantworten.

Re: Klassen

Verfasst: Freitag 4. Dezember 2015, 17:12
von mutetella
@BMTP
  1. Klassen bilden einen eigenen Namensraum, einer der Gründe, weshalb man sie ja auch nutzt. Das heißt, die Namen, die in Deiner `__init__()` Methode erstellt werden, gelten innerhalb der gesamten Klasse. Es ist also nicht nötig, an die Methode `getGrussformel()` nochmals `vorname` und `nachname` zu übergeben.
  2. `getGrussformel` ist in der Python Hemisphäre (schau' mal pep 8 an) kein guter Name für eine Methode. In Python nennt man sowas `get_grussformel()`, wobei man eigentlich auch das `get_` weglassen kann, da man in Python auch keine getter oder setter Methoden verwendet. Aber das musst Du mit Deinem Lehrer ausmachen... ;-)
  3. Innerhalb Deiner `getGrussformel()` Methode erstellst Du einen neuen Namen `getGrussformel` und bindest diesen an ein Tupel, das 3 Elemente enthält: 1. einen String 'Sehr geehrter Herr ', 2. das, was an `vorname` und 3. das was an `nachname` übergeben wird. Das ist ja nicht, was Du eigentlich möchtest!
  4. Jetzt heißt Deine Methode schon `get...`, jetzt musst Du auch etwas getten, will heißen zurückgeben. Das tust Du nicht, deshalb erhältst Du `None`. Wenn man innerhalb einer Funktion/Methode (was letztlich auch eine Funktion ist, nur halt innerhalb einer Klasse) nicht explizit etwas zurückgibt, erhältst Du eben `None`.
  5. Zuletzt solltest Du Dich einmal damit auseinandersetzen, was dieses ominöse `self` zu bedeuten hat. Dann kannst Du auch innerhalb `getGrussformel` auf die Instanzattribute (ich finde in diesem Zusammenhang für das englische Instance die Übersetzung 'Exemplar' statt 'Instanz' ja besser), die Du ja beim Erstellen eines Exemplares der Klasse `Person` bereits festlegst, auch zugreifen.
Schau' Dir einfach auch mal das offizielle Python Tutorial und darin vor allem das Kapitel der Klassen an. Dabei wird Dir so einiges klar werden.

Re: Klassen

Verfasst: Freitag 4. Dezember 2015, 17:24
von BMTP
Also, ich habe den Code jetzt mal so umgeändert:

Code: Alles auswählen

class Person(object):
    def __init__(self, vorname, nachname, geschlecht, alter):
        self.vorname = vorname
        self.nachname = nachname
        self.geschlecht = geschlecht
        self.alter = alter

    def getGrussformel(self):
        if self.geschlecht == "M" and self.alter > 18:
            getGrussformel = "Sehr geehrter Herr " + self.vorname + self.nachname


        elif self.geschlecht == "W" and self.alter > 18 :
            getGrussformel = "Sehr geehrte Frau "+ self.vorname + self.nachname


        else:
            getGrussformel = "Hallo " + self.vorname
return getGrussformel()

@mutetella: zu deinem zweiten Punkt, an dem Namen kann ich leider auch nichts ändern :D

Der vorgegebene Code (siehe Anfangspost) darf auch von uns nicht verändern werden. Das String object führt jetzt wie erwartet zu Problemen, was heißt ich muss die getGrussformel anders ausgeben ohne den String zu benutzen.

Re: Klassen

Verfasst: Freitag 4. Dezember 2015, 17:33
von mutetella
@BMTP
Versuch' doch mal zu erklären, weshalb Du innerhalb der Methode `getGrussformel()` einen Namen `getGrussformel` erstellst, an den Du einen String bindest?

Re: Klassen

Verfasst: Freitag 4. Dezember 2015, 17:36
von mutetella
EDIT: Sorry, hab' das `return` statement übersehen, da es nicht mehr innerhalb des Codebox steht. Schau' Dir mal genau an, was Du da zurückgibst. Jedenfalls nicht den String, den Du eigentlich zurückgeben möchtest. Und das, was ich zuerst zu den Namen geschrieben hab', hat trotzdem noch seine Gültigkeit... ;-)

Re: Klassen

Verfasst: Freitag 4. Dezember 2015, 17:41
von BMTP
@ mutetella Also wenn ich das return in

Code: Alles auswählen

return getGrussformel
ändere, dann bekomme ich eine Ausgabe (ein Schritt Erfolg juhhu :D ) allerdings ist jetzt einiges vertauscht:

Hallo Ina
Sehr geehrter Herr PeterMeier
Hallo Jan
Hallo Lisa

Also stimmt an meinen if-Bedingungen etwas nicht. Person A wird falsch wiedergegeben.

Edit: Ok, ich muss ja die Bedingung >= 18 machen. Jetzt stimmt die Ausgabe. Gibt es einen Weg, dass Vorname und Nachname auseinander geschrieben wird? Ansonsten müsste das Programm ja jetzt stimmen.

Re: Klassen

Verfasst: Freitag 4. Dezember 2015, 17:46
von mutetella
@BMTP
Die Frequenz Deiner Antworten lässt mich vermuten, dass Du so ein wenig nach Try`n`Error vorgehst, was beim Programmieren in die Hose geht. Lies Dir einfach nochmal in Ruhe BlackJack's Beitrag durch. Und wenn ich eine Funktion habe, die zwar keinen Fehler provoziert, aber auch nicht das ausspuckt, was ich erwarte, dann nehm' ich auch gerne mal Papier und Bleistift und skizziere, was da im Einzelnen passiert...

Re: Klassen

Verfasst: Freitag 4. Dezember 2015, 18:22
von noisefloor
Hallo,
Gibt es einen Weg, dass Vorname und Nachname auseinander geschrieben wird?
Natürlich. Die Stichworte, nach denen du Suchen möchtest heißen "python string formating" oder "python string format". Ist aber mit Sicherheit im auch im Python-Tutorial erklärt.

Gruß, noisefloor