Zum Inhalt springen
Python Fortgeschritten 4 min

Projekt: Taschenrechner in Python

Baue einen vollständigen Taschenrechner mit Fehlerbehandlung, Verlauf und erweiterten Operationen - dein erstes Python-Praxisprojekt

Aktualisiert:

Projekt: Taschenrechner in Python

In diesem Projekt bauen wir Schritt für Schritt einen vollständigen Taschenrechner in Python. Du wirst dabei viele der Konzepte anwenden, die du bisher gelernt hast — von Funktionen über Schleifen bis hin zur Fehlerbehandlung.

Projektübersicht und Ziele

Unser Taschenrechner soll folgende Funktionen bieten:

  • Grundrechenarten: Addition, Subtraktion, Multiplikation, Division
  • Erweiterte Operationen: Potenz, Wurzel, Modulo
  • Benutzermenü: Interaktive Bedienung über die Konsole
  • Fehlerbehandlung: Sinnvolle Fehlermeldungen bei ungültigen Eingaben
  • Verlauf: Alle Berechnungen werden gespeichert und können angezeigt werden

Am Ende hast du ein voll funktionsfähiges Programm, das du nach Belieben erweitern kannst.


Schritt 1: Grundoperationen definieren

Wir beginnen mit den vier Grundrechenarten als einzelne Funktionen:

def addieren(a, b):
    """Addiert zwei Zahlen."""
    return a + b

def subtrahieren(a, b):
    """Subtrahiert b von a."""
    return a - b

def multiplizieren(a, b):
    """Multipliziert zwei Zahlen."""
    return a * b

def dividieren(a, b):
    """Dividiert a durch b."""
    if b == 0:
        raise ValueError("Division durch 0 ist nicht erlaubt!")
    return a / b

Jede Funktion hat eine klare Aufgabe. Bei der Division prüfen wir bereits, ob durch Null geteilt wird, und werfen in diesem Fall einen Fehler.

Testen wir die Funktionen:

print(addieren(10, 5))       # 15
print(subtrahieren(10, 5))   # 5
print(multiplizieren(10, 5)) # 50
print(dividieren(10, 5))     # 2.0

Schritt 2: Benutzereingabe und Menü

Jetzt bauen wir ein interaktives Menü, damit der Benutzer den Taschenrechner bedienen kann:

def menue_anzeigen():
    """Zeigt das Hauptmenü an."""
    print("\n" + "=" * 40)
    print("    PYTHON TASCHENRECHNER")
    print("=" * 40)
    print("1. Addition (+)")
    print("2. Subtraktion (-)")
    print("3. Multiplikation (*)")
    print("4. Division (/)")
    print("5. Beenden")
    print("=" * 40)

def zahlen_eingeben():
    """Fragt den Benutzer nach zwei Zahlen."""
    zahl1 = float(input("Erste Zahl eingeben: "))
    zahl2 = float(input("Zweite Zahl eingeben: "))
    return zahl1, zahl2

# Hauptschleife
while True:
    menue_anzeigen()
    auswahl = input("Wähle eine Operation (1-5): ")

    if auswahl == "5":
        print("Auf Wiedersehen!")
        break

    if auswahl in ("1", "2", "3", "4"):
        zahl1, zahl2 = zahlen_eingeben()

        if auswahl == "1":
            ergebnis = addieren(zahl1, zahl2)
            print(f"\n{zahl1} + {zahl2} = {ergebnis}")
        elif auswahl == "2":
            ergebnis = subtrahieren(zahl1, zahl2)
            print(f"\n{zahl1} - {zahl2} = {ergebnis}")
        elif auswahl == "3":
            ergebnis = multiplizieren(zahl1, zahl2)
            print(f"\n{zahl1} * {zahl2} = {ergebnis}")
        elif auswahl == "4":
            ergebnis = dividieren(zahl1, zahl2)
            print(f"\n{zahl1} / {zahl2} = {ergebnis}")
    else:
        print("Ungültige Auswahl! Bitte wähle 1-5.")

Die while True-Schleife sorgt dafür, dass das Programm so lange läuft, bis der Benutzer “5” für Beenden wählt.


Schritt 3: Fehlerbehandlung

Unser Programm kann noch abstürzen, wenn der Benutzer keine gültige Zahl eingibt. Das beheben wir mit try/except:

def zahlen_eingeben():
    """Fragt den Benutzer nach zwei Zahlen mit Fehlerbehandlung."""
    while True:
        try:
            zahl1 = float(input("Erste Zahl eingeben: "))
            zahl2 = float(input("Zweite Zahl eingeben: "))
            return zahl1, zahl2
        except ValueError:
            print("Fehler: Bitte gib gültige Zahlen ein!")

def berechnung_ausfuehren(auswahl, zahl1, zahl2):
    """Führt die gewählte Berechnung aus und behandelt Fehler."""
    try:
        if auswahl == "1":
            ergebnis = addieren(zahl1, zahl2)
            operator = "+"
        elif auswahl == "2":
            ergebnis = subtrahieren(zahl1, zahl2)
            operator = "-"
        elif auswahl == "3":
            ergebnis = multiplizieren(zahl1, zahl2)
            operator = "*"
        elif auswahl == "4":
            ergebnis = dividieren(zahl1, zahl2)
            operator = "/"
        else:
            return None

        print(f"\n  Ergebnis: {zahl1} {operator} {zahl2} = {ergebnis}")
        return ergebnis
    except ValueError as e:
        print(f"\n  Fehler: {e}")
        return None

Jetzt fangen wir sowohl ungültige Eingaben als auch Division durch Null sauber ab, ohne dass das Programm abstürzt.


Schritt 4: Verlauf / History speichern

Wir fügen eine Liste hinzu, die alle bisherigen Berechnungen speichert:

verlauf = []

def zum_verlauf_hinzufuegen(zahl1, operator, zahl2, ergebnis):
    """Speichert eine Berechnung im Verlauf."""
    eintrag = {
        "rechnung": f"{zahl1} {operator} {zahl2} = {ergebnis}",
        "zahl1": zahl1,
        "operator": operator,
        "zahl2": zahl2,
        "ergebnis": ergebnis
    }
    verlauf.append(eintrag)

def verlauf_anzeigen():
    """Zeigt alle bisherigen Berechnungen an."""
    if not verlauf:
        print("\nKein Verlauf vorhanden.")
        return

    print("\n" + "-" * 40)
    print("    BERECHNUNGSVERLAUF")
    print("-" * 40)
    for i, eintrag in enumerate(verlauf, 1):
        print(f"  {i}. {eintrag['rechnung']}")
    print("-" * 40)
    print(f"  Gesamt: {len(verlauf)} Berechnungen")

def verlauf_loeschen():
    """Löscht den gesamten Verlauf."""
    verlauf.clear()
    print("\nVerlauf wurde gelöscht.")

Das Menü erweitern wir um die Optionen “Verlauf anzeigen” und “Verlauf löschen”.


Schritt 5: Erweiterte Operationen

Jetzt fügen wir Potenz, Quadratwurzel und Modulo hinzu:

import math

def potenz(a, b):
    """Berechnet a hoch b."""
    return a ** b

def wurzel(a):
    """Berechnet die Quadratwurzel von a."""
    if a < 0:
        raise ValueError("Quadratwurzel einer negativen Zahl ist nicht definiert!")
    return math.sqrt(a)

def modulo(a, b):
    """Berechnet den Rest der Division a / b."""
    if b == 0:
        raise ValueError("Modulo durch 0 ist nicht erlaubt!")
    return a % b

Die Wurzel-Funktion ist besonders, weil sie nur eine Zahl benötigt. Das berücksichtigen wir in der Eingabelogik:

def eine_zahl_eingeben():
    """Fragt den Benutzer nach einer Zahl."""
    while True:
        try:
            zahl = float(input("Zahl eingeben: "))
            return zahl
        except ValueError:
            print("Fehler: Bitte gib eine gültige Zahl ein!")

Schritt 6: Code mit Funktionen organisieren

Jetzt bringen wir alles zusammen in einer sauber organisierten Struktur:

import math

# ============================================
# BERECHNUNGSFUNKTIONEN
# ============================================

def addieren(a, b):
    return a + b

def subtrahieren(a, b):
    return a - b

def multiplizieren(a, b):
    return a * b

def dividieren(a, b):
    if b == 0:
        raise ValueError("Division durch 0 ist nicht erlaubt!")
    return a / b

def potenz(a, b):
    return a ** b

def wurzel(a):
    if a < 0:
        raise ValueError("Quadratwurzel negativer Zahlen nicht definiert!")
    return math.sqrt(a)

def modulo(a, b):
    if b == 0:
        raise ValueError("Modulo durch 0 ist nicht erlaubt!")
    return a % b

# ============================================
# OPERATIONEN-ZUORDNUNG
# ============================================

operationen = {
    "1": {"name": "Addition", "symbol": "+", "funktion": addieren, "args": 2},
    "2": {"name": "Subtraktion", "symbol": "-", "funktion": subtrahieren, "args": 2},
    "3": {"name": "Multiplikation", "symbol": "*", "funktion": multiplizieren, "args": 2},
    "4": {"name": "Division", "symbol": "/", "funktion": dividieren, "args": 2},
    "5": {"name": "Potenz", "symbol": "^", "funktion": potenz, "args": 2},
    "6": {"name": "Quadratwurzel", "symbol": "√", "funktion": wurzel, "args": 1},
    "7": {"name": "Modulo", "symbol": "%", "funktion": modulo, "args": 2},
}

Durch das Dictionary operationen vermeiden wir lange if/elif-Ketten und machen den Code leicht erweiterbar.


Vollständiger Code

Hier ist das komplette Programm mit allen Funktionen:

import math

# ============================================
# BERECHNUNGSFUNKTIONEN
# ============================================

def addieren(a, b):
    """Addiert zwei Zahlen."""
    return a + b

def subtrahieren(a, b):
    """Subtrahiert b von a."""
    return a - b

def multiplizieren(a, b):
    """Multipliziert zwei Zahlen."""
    return a * b

def dividieren(a, b):
    """Dividiert a durch b."""
    if b == 0:
        raise ValueError("Division durch 0 ist nicht erlaubt!")
    return a / b

def potenz(a, b):
    """Berechnet a hoch b."""
    return a ** b

def wurzel(a):
    """Berechnet die Quadratwurzel."""
    if a < 0:
        raise ValueError("Quadratwurzel negativer Zahlen nicht definiert!")
    return math.sqrt(a)

def modulo(a, b):
    """Berechnet a modulo b."""
    if b == 0:
        raise ValueError("Modulo durch 0 ist nicht erlaubt!")
    return a % b

# ============================================
# OPERATIONEN-DICTIONARY
# ============================================

operationen = {
    "1": {"name": "Addition", "symbol": "+", "funktion": addieren, "args": 2},
    "2": {"name": "Subtraktion", "symbol": "-", "funktion": subtrahieren, "args": 2},
    "3": {"name": "Multiplikation", "symbol": "*", "funktion": multiplizieren, "args": 2},
    "4": {"name": "Division", "symbol": "/", "funktion": dividieren, "args": 2},
    "5": {"name": "Potenz", "symbol": "^", "funktion": potenz, "args": 2},
    "6": {"name": "Quadratwurzel", "symbol": "√", "funktion": wurzel, "args": 1},
    "7": {"name": "Modulo", "symbol": "%", "funktion": modulo, "args": 2},
}

# ============================================
# VERLAUF
# ============================================

verlauf = []

def zum_verlauf_hinzufuegen(rechnung_text, ergebnis):
    """Speichert eine Berechnung im Verlauf."""
    verlauf.append({"rechnung": rechnung_text, "ergebnis": ergebnis})

def verlauf_anzeigen():
    """Zeigt den Berechnungsverlauf an."""
    if not verlauf:
        print("\n  Kein Verlauf vorhanden.")
        return
    print("\n" + "-" * 40)
    print("    BERECHNUNGSVERLAUF")
    print("-" * 40)
    for i, eintrag in enumerate(verlauf, 1):
        print(f"  {i}. {eintrag['rechnung']} = {eintrag['ergebnis']}")
    print("-" * 40)
    print(f"  Gesamt: {len(verlauf)} Berechnungen")

def verlauf_loeschen():
    """Löscht den gesamten Verlauf."""
    verlauf.clear()
    print("\n  Verlauf wurde gelöscht.")

# ============================================
# EINGABEFUNKTIONEN
# ============================================

def zahl_eingeben(prompt="Zahl eingeben: "):
    """Fragt nach einer Zahl mit Fehlerbehandlung."""
    while True:
        try:
            return float(input(prompt))
        except ValueError:
            print("  Fehler: Bitte gib eine gültige Zahl ein!")

def menue_anzeigen():
    """Zeigt das Hauptmenü an."""
    print("\n" + "=" * 40)
    print("    PYTHON TASCHENRECHNER")
    print("=" * 40)
    for key, op in operationen.items():
        print(f"  {key}. {op['name']} ({op['symbol']})")
    print()
    print("  8. Verlauf anzeigen")
    print("  9. Verlauf löschen")
    print("  0. Beenden")
    print("=" * 40)

# ============================================
# HAUPTPROGRAMM
# ============================================

def main():
    """Startet den Taschenrechner."""
    print("\nWillkommen beim Python Taschenrechner!")

    while True:
        menue_anzeigen()
        auswahl = input("Deine Wahl: ").strip()

        # Beenden
        if auswahl == "0":
            print("\nDanke fürs Rechnen! Auf Wiedersehen!")
            break

        # Verlauf anzeigen
        if auswahl == "8":
            verlauf_anzeigen()
            continue

        # Verlauf löschen
        if auswahl == "9":
            verlauf_loeschen()
            continue

        # Berechnung ausführen
        if auswahl in operationen:
            op = operationen[auswahl]
            print(f"\n--- {op['name']} ---")

            try:
                if op["args"] == 2:
                    a = zahl_eingeben("Erste Zahl: ")
                    b = zahl_eingeben("Zweite Zahl: ")
                    ergebnis = op["funktion"](a, b)
                    rechnung = f"{a} {op['symbol']} {b}"
                else:
                    a = zahl_eingeben("Zahl: ")
                    ergebnis = op["funktion"](a)
                    rechnung = f"{op['symbol']}({a})"

                # Ergebnis anzeigen
                print(f"\n  {rechnung} = {ergebnis}")

                # Im Verlauf speichern
                zum_verlauf_hinzufuegen(rechnung, ergebnis)

            except ValueError as e:
                print(f"\n  Fehler: {e}")
        else:
            print("\n  Ungültige Auswahl! Bitte wähle 0-9.")

# Programm starten
if __name__ == "__main__":
    main()

So funktioniert der vollständige Code:

  1. Funktionen oben: Alle Berechnungsfunktionen sind klar definiert und dokumentiert.
  2. Dictionary für Operationen: Statt langer if/elif-Ketten nutzen wir ein Dictionary, das jeder Menüoption eine Funktion zuordnet.
  3. Verlauf als Liste: Jede Berechnung wird als Dictionary in einer Liste gespeichert.
  4. Hauptschleife: Die main()-Funktion enthält die Programmlogik in einer übersichtlichen Schleife.
  5. Fehlerbehandlung: try/except fängt alle möglichen Fehler ab.

Erweiterungsideen

Wenn du den Taschenrechner weiter ausbauen möchtest, hier einige Vorschläge:

  • Wissenschaftliche Funktionen: Sinus, Cosinus, Tangens, Logarithmus mit dem math-Modul
  • Klammern und Ausdrücke: Ganze mathematische Ausdrücke wie (3 + 5) * 2 parsen
  • GUI mit tkinter: Eine grafische Oberfläche wie ein echter Taschenrechner
  • Verlauf in Datei speichern: Mit json-Modul den Verlauf persistent machen
  • Einheitenumrechnung: Kilometer zu Meilen, Celsius zu Fahrenheit usw.
  • Letzte Ergebnis verwenden: Das vorherige Ergebnis in der nächsten Berechnung nutzen

Was du gelernt hast

In diesem Projekt hast du folgende Konzepte praktisch angewendet:

  • Funktionen definieren und aufrufen — jede Operation ist eine eigene Funktion
  • Dictionaries — zur eleganten Zuordnung von Menüoptionen zu Funktionen
  • While-Schleifen — für das interaktive Menü und die Eingabevalidierung
  • Try/Except — für robuste Fehlerbehandlung
  • Listen — zum Speichern des Berechnungsverlaufs
  • f-Strings — für formatierte Ausgaben
  • Module importierenmath für erweiterte Berechnungen
  • Code-Organisation — Aufteilung in logische Abschnitte

Pro-Tipp: Wenn du den Taschenrechner als OOP-Projekt umbauen möchtest, erstelle eine Taschenrechner-Klasse, die den Verlauf als Attribut speichert und die Operationen als Methoden enthält. Das ist eine hervorragende Übung, um Klassen in einem realen Kontext zu verwenden!

class Taschenrechner:
    def __init__(self):
        self.verlauf = []

    def addieren(self, a, b):
        ergebnis = a + b
        self._speichern(f"{a} + {b}", ergebnis)
        return ergebnis

    def _speichern(self, rechnung, ergebnis):
        self.verlauf.append({"rechnung": rechnung, "ergebnis": ergebnis})
Zurück zum Python Kurs