Berechnung in Klassen funktioniert nicht

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
Fin97
User
Beiträge: 5
Registriert: Freitag 18. Dezember 2015, 17:43

Guten Tag,
ich habe gerade ein kleines Problem mit der Definition einer Klasse.

Meine Klasse sieht derzeit wie folgt aus:

Code: Alles auswählen

class Angestelter():
    def __init__(self):
        self.name=""
        self.basisfreibetrag=10
        self.zusatzfreibetrag=5
        self.gehalt=30
        self.taetigkeit=""
        self.steuern=0
        
    def steuernberechnen(self):
        self.steuern=45/100*(self.gehalt - (self.basisfreibetrag + self.zusatzfreibetrag))
Nun sollen eigentlich durch die untere Funktion die Steuern berechnet werden.

Wenn ich aber jetzt mit:

Code: Alles auswählen

objekt=Angestellter()
print (objekt.steuer)
die Steuern ausgeben möchte,
gibt er mit 0 anstatt 8,1

Kann mir einer sagen wo mein Denkfehler liegt?
ich könnte mir vorstellen, dass ich den Wert self.steuern noch irgendwie zurückgeben muss?

Viele Grüße,
Fin
Zuletzt geändert von Anonymous am Freitag 18. Dezember 2015, 18:52, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

1. Bitte benutz den code-tag hier, um deinen Code vernuenftig zu formatieren
2. Du betreibst Ganzzahl-Arithmetik. Da koennen keine Fliesskommazahlen bei rumkommen - mit Python2.

Du kannst das dadurch abaendern, dass du entweder Fliesskommazahlen verwendest (also self.gehalt = 30.0 etc.), oder Python dazu bringst - wie in der Version 3 grundsaetzlich - den Divisonsoperator immer als Fliesskommaoperator zu behandlen.

Das machst du durch ein

Code: Alles auswählen

from __future__ import division
in der ersten Zeile deines Moduls. ACHTUNG: das gilt dann *nur* fuer diese Modul!
Fin97
User
Beiträge: 5
Registriert: Freitag 18. Dezember 2015, 17:43

Ok :)
Werde ich mal probieren.
Kann ich das ganze eigentlich auch durch Runden lösen?

Code: Alles auswählen

self.steuern=round(45/100*(self.gehalt - (self.basisfreibetrag + self.zusatzfreibetrag)), 3)
BlackJack

@Fin97: Beim ersten Quelltext hättest Du einen `AttributeError` bekommen weil das Objekt kein `steuer`-Attribut hat. Hättest Du ``objekt.steuern`` geschrieben wäre 0 ausgegeben worden weil im Beispiel das Attribut nun mal den Wert 0 hat wenn man die `steuernberechnen()`-Methode nicht vorher aufgerufen hat. An der Stelle merkt man dann auch warum das kein (normales) Attribut sein sollte: Der Wert hängt vom Wert von anderen Attributen ab und wenn die sich ändern, dann müsste sich auch `steuern` ändern. Also sollte man da ein Methode `berechne_steuern()` draus machen die den Wert als Ergebnis zurück gibt und nicht den Zustand des Objekts ändert oder ein `property()`, so dass der Wert immer aktuell berechnet wird wenn man ihn benötigt.

In diesem Zustand/Umfang macht die Klasse übrigens keinen Sinn. Das hätte man auch viel einfacher als Funktion schreiben können.

Was Du hier jetzt mit Runden anfangen willst ist mir nicht so ganz klar‽
Fin97
User
Beiträge: 5
Registriert: Freitag 18. Dezember 2015, 17:43

Wie kann ich denn den Wert zurückgeben?
Das Runden ist deswegen da, da ich keine Nachkommastellen benötige.
BlackJack

@Fin97: Vor Klassen sollte man sich mal mit Funktionen beschäftigt haben und von da kennt man ``return``. Und wie gesagt, die Klasse dort ist bisher eine recht umständliche Art eine Funktion zu schreiben. Was zusätzlich noch dadurch verschärft wird das alle Angestellten keinen Namen und keine Tätigkeit haben, aber schon einen festen Wert für das Gehalt. Das sind ja alles Sachen die man eigentlich doch ganz gerne abgeben können möchte wenn man ein `Angestelter`-Exemplar (sic!) erstellt.

Letztlich ist das wie gesagt eine einfache Funktion, da braucht man keine Klasse für:

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function


def berechne_steuern(gehalt, basisfreibetrag, zusatzfreibetrag):
    return 0.45 * (gehalt - (basisfreibetrag + zusatzfreibetrag))


def main():
    print(berechne_steuern(10, 5, 30))


if __name__ == '__main__':
    main()

Du benötigst *keine* Nachkommastellen, rundest aber auf 3 Nachkommastellen‽ Wenn man gar keine braucht, dann wandelt man das Ergebnis doch besser in eine ganze Zahl um oder benutzt die passende dedizierte Funktion aus dem `math`-Modul. Also `trunc()` oder `floor()`.

Wir wissen übrigens immer noch nicht woran das Problem denn nun lag/liegt, also ob Du die Methode nicht aufgerufen hast oder ob Du Python 2 verwendest. Darum ist es immer eine gute Idee den tatsächlichen Code mit dem tatsächlichen Ergebnis zu zeigen und nicht Code der so ähnlich ist wie der der Probleme bereitet.
Benutzeravatar
noisefloor
User
Beiträge: 3854
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

das läuft schon alles korrekt - dir fehlt da offensichtlich aber das Verständnis, was das abläuft...

Mit

Code: Alles auswählen

objekt=Angestellter()
legst du eine Instanz Names `objekt` von der Klasse `Angesteller` an. Dabei ruft der Python-Interpreter automatisch nur die `__init__` Methode auf - und (in diesem Fall) KEINE andere Methode. Da in der __init__ Methode `self.steuer=0` definiert ist, gibt `object.steuer` logischerweise 0 aus - das ändert sich, wenn du `objekt.steuerberechnung()` aufrufen würdest...

Was an der Klassen an sich suboptimal ist hat BlackJack ja schon ausgeführt...

Gruß, noisefloor
Antworten