(Der Beitrag war eine Weile in Bearbeitung, darum gibt es Überschneidungen mit bereits geschriebenen.)
@oldboyJR: Anmerkungen zum Quelltext:
Eingerückt wird per Konvention vier Leerzeichen pro Ebene.
Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.
Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).
Namen sollten keine kryptischen Abkürzungen enthalten oder gar nur daraus bestehen. Der Name soll dem Leser vermitteln was der Wert dahinter im Programm bedeutet, nicht zum rätseln zwingen.
Man nummeriert keine Namen. Dann will man sich entweder bessere Namen überlegen, oder gar keine Einzelnamen/-werte verwenden, sondern eine Datenstruktur. Oft eine Liste.
Grunddatentypen haben nichts in Namen verloren. Den Typen ändert man gar nicht so selten mal während der Programmentwicklung und dann muss man überall im Programm die betroffenen Namen ändern, oder man hat falsche, irreführende Namen im Quelltext.
`J`, `Fak`, und `hoechs` auf Modulebene werden nirgends verwendet.
Die ganzen `KLIST*`-Namen sind nicht nur nummeriert, sondern die Namen enthalten Daten die in den Listen noch mal als Werte wiederholt werden. Die ganzen Namen kann man sich sparen wenn man die Listen selbst einfach in eine Liste steckt:
Code: Alles auswählen
KS = [
[2005, 1, 0.4, 1900],
[2006, 2, 0.384, 1824],
[2007, 3, 0.368, 1748],
[2008, 4, 0.352, 1672],
[2009, 5, 0.336, 1596],
[2010, 6, 0.32, 1520],
[2011, 7, 0.304, 1444],
[2012, 8, 0.288, 1368],
[2013, 9, 0.272, 1292],
[2014, 10, 0.256, 1216],
[2015, 11, 0.24, 1140],
[2016, 12, 0.224, 1064],
[2017, 13, 0.208, 988],
[2018, 14, 0.192, 912],
[2019, 15, 0.176, 836],
[2020, 16, 0.16, 760],
[2021, 17, 0.152, 722],
[2022, 18, 0.144, 684],
[2023, 19, 0.136, 646],
[2024, 20, 0.128, 608],
[2025, 21, 0.12, 570],
[2026, 22, 0.112, 532],
[2027, 23, 0.104, 494],
[2028, 24, 0.096, 456],
[2029, 25, 0.088, 418],
[2030, 26, 0.08, 380],
[2031, 27, 0.072, 342],
[2032, 28, 0.064, 304],
[2033, 29, 0.056, 266],
[2034, 30, 0.048, 228],
[2035, 31, 0.04, 190],
[2036, 32, 0.032, 152],
[2037, 33, 0.024, 114],
[2038, 34, 0.016, 76],
[2039, 35, 0.008, 38],
[2040, 36, 0, 0],
]
Die Abbildung von Jahr auf diese Listen kann man dann einfach mit einer Schleife oder einer „dict comprehension“ erzeugen:
Code: Alles auswählen
JAHR_ZU_DATENSATZ = {datensatz[0]: datensatz for datensatz in KS}
Oder man spart sich die Aufteilung in zwei Schritte und schreibt gleich das Wörterbuch in den Quelltext:
Code: Alles auswählen
JAHR_ZU_DATENSATZ = {
2005: [2005, 1, 0.4, 1900],
2006: [2006, 2, 0.384, 1824],
2007: [2007, 3, 0.368, 1748],
2008: [2008, 4, 0.352, 1672],
2009: [2009, 5, 0.336, 1596],
2010: [2010, 6, 0.32, 1520],
2011: [2011, 7, 0.304, 1444],
2012: [2012, 8, 0.288, 1368],
2013: [2013, 9, 0.272, 1292],
2014: [2014, 10, 0.256, 1216],
2015: [2015, 11, 0.24, 1140],
2016: [2016, 12, 0.224, 1064],
2017: [2017, 13, 0.208, 988],
2018: [2018, 14, 0.192, 912],
2019: [2019, 15, 0.176, 836],
2020: [2020, 16, 0.16, 760],
2021: [2021, 17, 0.152, 722],
2022: [2022, 18, 0.144, 684],
2023: [2023, 19, 0.136, 646],
2024: [2024, 20, 0.128, 608],
2025: [2025, 21, 0.12, 570],
2026: [2026, 22, 0.112, 532],
2027: [2027, 23, 0.104, 494],
2028: [2028, 24, 0.096, 456],
2029: [2029, 25, 0.088, 418],
2030: [2030, 26, 0.08, 380],
2031: [2031, 27, 0.072, 342],
2032: [2032, 28, 0.064, 304],
2033: [2033, 29, 0.056, 266],
2034: [2034, 30, 0.048, 228],
2035: [2035, 31, 0.04, 190],
2036: [2036, 32, 0.032, 152],
2037: [2037, 33, 0.024, 114],
2038: [2038, 34, 0.016, 76],
2039: [2039, 35, 0.008, 38],
2040: [2040, 36, 0, 0],
}
Was hier jetzt auf den ersten Blick auffällt, ist das die Jahreszahl da immer zweimal drin steht. Das muss nicht sein, denn die Jahreszahl hat man ja bereits, sonst könnte man darüber nicht auf die dazugehörigen Daten zugreifen:
Code: Alles auswählen
JAHR_ZU_DATENSATZ = {
2005: [1, 0.4, 1900],
2006: [2, 0.384, 1824],
2007: [3, 0.368, 1748],
2008: [4, 0.352, 1672],
2009: [5, 0.336, 1596],
2010: [6, 0.32, 1520],
2011: [7, 0.304, 1444],
2012: [8, 0.288, 1368],
2013: [9, 0.272, 1292],
2014: [10, 0.256, 1216],
2015: [11, 0.24, 1140],
2016: [12, 0.224, 1064],
2017: [13, 0.208, 988],
2018: [14, 0.192, 912],
2019: [15, 0.176, 836],
2020: [16, 0.16, 760],
2021: [17, 0.152, 722],
2022: [18, 0.144, 684],
2023: [19, 0.136, 646],
2024: [20, 0.128, 608],
2025: [21, 0.12, 570],
2026: [22, 0.112, 532],
2027: [23, 0.104, 494],
2028: [24, 0.096, 456],
2029: [25, 0.088, 418],
2030: [26, 0.08, 380],
2031: [27, 0.072, 342],
2032: [28, 0.064, 304],
2033: [29, 0.056, 266],
2034: [30, 0.048, 228],
2035: [31, 0.04, 190],
2036: [32, 0.032, 152],
2037: [33, 0.024, 114],
2038: [34, 0.016, 76],
2039: [35, 0.008, 38],
2040: [36, 0, 0],
}
Immer noch recht offensichtlich kann man den ersten Wert jeder Liste trivial aus der Jahreszahl ermitteln. Das ist ja einfach ``jahr - 2005 + 1``. Die ganzen Werte muss man da nicht in den Code schreiben:
Code: Alles auswählen
JAHR_ZU_DATENSATZ = {
2005: [0.4, 1900],
2006: [0.384, 1824],
2007: [0.368, 1748],
2008: [0.352, 1672],
2009: [0.336, 1596],
2010: [0.32, 1520],
2011: [0.304, 1444],
2012: [0.288, 1368],
2013: [0.272, 1292],
2014: [0.256, 1216],
2015: [0.24, 1140],
2016: [0.224, 1064],
2017: [0.208, 988],
2018: [0.192, 912],
2019: [0.176, 836],
2020: [0.16, 760],
2021: [0.152, 722],
2022: [0.144, 684],
2023: [0.136, 646],
2024: [0.128, 608],
2025: [0.12, 570],
2026: [0.112, 532],
2027: [0.104, 494],
2028: [0.096, 456],
2029: [0.088, 418],
2030: [0.08, 380],
2031: [0.072, 342],
2032: [0.064, 304],
2033: [0.056, 266],
2034: [0.048, 228],
2035: [0.04, 190],
2036: [0.032, 152],
2037: [0.024, 114],
2038: [0.016, 76],
2039: [0.008, 38],
2040: [0, 0],
}
Nicht ganz so offensichtlich, aber auch diese Daten lassen sich aus der Jahreszahl einfach ausrechnen.
Code: Alles auswählen
START_JAHR = 2005
END_JAHR = 2040
START_FAKTOR = 0.4
START_HOECHSTBETRAG = 1900
FAKTOR_DELTA = 0.016
HOECHSTBETRAG_DELTA = 76
HALBIERUNG_NACH = 15 # in Jahren.
def berechne_wert(startwert, jahre_voll, jahre_halb, delta):
return startwert - jahre_voll * delta - jahre_halb * delta / 2
def berechne_datensatz(jahr):
jahre = jahr - START_JAHR
jahre_voll = min(jahre, HALBIERUNG_NACH)
jahre_halb = max(jahre - HALBIERUNG_NACH, 0)
return (
round(
berechne_wert(START_FAKTOR, jahre_voll, jahre_halb, FAKTOR_DELTA),
4,
),
berechne_wert(
START_HOECHSTBETRAG, jahre_voll, jahre_halb, HOECHSTBETRAG_DELTA
),
)
assert berechne_datensatz(END_JAHR) == (0, 0)
Damit zum testen das Wörterbuch erstellt:
Code: Alles auswählen
In [330]: {jahr: berechne_datensatz(jahr) for jahr in range(START_JAHR, END_JAHR + 1)}
Out[330]:
{2005: (0.4, 1900.0),
2006: (0.384, 1824.0),
2007: (0.368, 1748.0),
2008: (0.352, 1672.0),
2009: (0.336, 1596.0),
2010: (0.32, 1520.0),
2011: (0.304, 1444.0),
2012: (0.288, 1368.0),
2013: (0.272, 1292.0),
2014: (0.256, 1216.0),
2015: (0.24, 1140.0),
2016: (0.224, 1064.0),
2017: (0.208, 988.0),
2018: (0.192, 912.0),
2019: (0.176, 836.0),
2020: (0.16, 760.0),
2021: (0.152, 722.0),
2022: (0.144, 684.0),
2023: (0.136, 646.0),
2024: (0.128, 608.0),
2025: (0.12, 570.0),
2026: (0.112, 532.0),
2027: (0.104, 494.0),
2028: (0.096, 456.0),
2029: (0.088, 418.0),
2030: (0.08, 380.0),
2031: (0.072, 342.0),
2032: (0.064, 304.0),
2033: (0.056, 266.0),
2034: (0.048, 228.0),
2035: (0.04, 190.0),
2036: (0.032, 152.0),
2037: (0.024, 114.0),
2038: (0.016, 76.0),
2039: (0.008, 38.0),
2040: (0.0, 0.0)}
Zur `erstellen()`-Funktion: Man definiert keine Namen am Anfang mit irgendwelchen Dummy-Werten die nie irgendwo verwendet werden. Namen werden dann eingeführt wenn man sie braucht und gleich mit sinnvollen Werten belegt wo immer das geht.
`list` ist der Name des Datentyps für Listen, den sollte man nicht an etwas anderes binden.
``while``, ``if``, und ``else`` ist so falsch. Das ``while`` sollte wohl ein ``if`` sein, denn `Jahr1` wird nirgends verändert im Schleifenkörper, womit das eine Endlosschleife ist. Das ``else`` ist so eingerückt das es zum ``while`` gehört, es sollte aber wohl zu dem ``if`` gehören was so eingerückt ist, dass es zum Schleifenkörper gehört. Die erste Anweisung im ``else``-Zweig ist ein Ausdruck der einen Wahrheitswert ergibt, mit dem dann aber nichts gemacht wird. Das sollte also wohl kein ``else`` sondern ein ``elif`` sein, mit dieser Bedingung.
Letztlich könnte man sich das aber auch alles sparen und die eingegebene Jahreszahl mit `min()` und `max()` auf den Tabellenbereich bringen.
Ungetestet:
Code: Alles auswählen
#!/usr/bin/env python3
START_JAHR = 2005
END_JAHR = 2040
START_FAKTOR = 0.4
START_HOECHSTBETRAG = 1900
FAKTOR_DELTA = 0.016
HOECHSTBETRAG_DELTA = 76
HALBIERUNG_NACH = 15 # in Jahren.
def berechne_wert(startwert, jahre_voll, jahre_halb, delta):
return startwert - jahre_voll * delta - jahre_halb * delta / 2
def berechne_datensatz(jahr):
jahre = jahr - START_JAHR
jahre_voll = min(jahre, HALBIERUNG_NACH)
jahre_halb = max(jahre - HALBIERUNG_NACH, 0)
return (
round(
berechne_wert(START_FAKTOR, jahre_voll, jahre_halb, FAKTOR_DELTA),
4,
),
berechne_wert(
START_HOECHSTBETRAG, jahre_voll, jahre_halb, HOECHSTBETRAG_DELTA
),
)
assert berechne_datensatz(END_JAHR) == (0, 0)
def main():
erstes_rentenjahr = int(input("geben sie das Jahr der ersten Rente ein ?"))
a_jahr = min(max(erstes_rentenjahr, START_JAHR), END_JAHR)
j = START_JAHR - a_jahr + 1
faktor, hoechstbetrag = berechne_datensatz(a_jahr)
if faktor == 0 and hoechstbetrag == 0:
print("Keine Tabellenwerte anrechenbar.")
elif faktor == START_FAKTOR and hoechstbetrag == START_HOECHSTBETRAG:
print("Sie haben die vollen Tabellenwerte.")
print(" Ajahr =", a_jahr)
print(" J =", j)
print("TAB2 Wert =", faktor)
print("TAB3 Wert =", hoechstbetrag)
if __name__ == "__main__":
main()