Home

Verbesserte Version des Pythagoras-Moduls mit Fehlerbehandlung, Klasse und Unit-Tests

Dieses Dokument beschreibt eine verbesserte Version des Pythagoras-Moduls in Python, die über einen C-Wrapper verfügt, Fehlerbehandlung integriert, eine Python-Klasse bereitstellt und umfassende Unit-Tests mit pytest enthält.


Wichtiger Hinweis (Juni 2026) : Bitte Teil 1, Vorgänger, als erstes verwenden!
Auch dieses Tutorial ist etwas älter und wurde nochmal überarbeitet. Mittlerweile ist Visual Studio 2026 am Markt, die Visual Studio 2022 Community Version wird bei Anwendern in langsam durch die Lizenzbedingungen von Microsoft verschwinden. Visual Code ist Microsofts neueste Option, und für bestimmte Anwendungsfälle vielleicht brauchbarer als Visual Studio. Aber die häufigen Updates, der etwas eigenwillige C/C++ Support mit diversen Extensions, die dann wieder veralten, lassen mich eher auf Abstand zu diesem Produkt gehen.
Im Quellcode selber befinden sich √ und 2 Anzeigen, die mit HTML Codes formatiert wurden. Viel Erfolg!

Projektstruktur

pythagoras_project/
|
+-- pythagoras.cpp        C-Quellcode (kompiert zu .pyd)
+-- pythagoras.py         Python-Wrapper mit Fehlerbehandlung & Klasse
+-- main.py               Demotest (Beispielanwendung)
+-- test_pythagoras.py    Unit-Tests mit pytest
+-- build.bat             Build-Script (für Windows)
+-- pythagoras_project.sln Visual Studio Projekt
    

1. Fehlerbehandlung

Wenn eine Eingabe negativ ist, wird eine ValueError ausgelöst, um ungültige Eingaben zu verhindern.

def _validate_positive(value: float, name: str) -> float:
    if value < 0:
        raise ValueError(f"{name} darf nicht negativ sein: {value}")
    return value
    

Beispiel: pythagoras.aufstellen(-1, 2) ? Fehler: "a darf nicht negativ sein: -1"

2. Klasse: PythagorasCalculator

Eine vollständige Python-Klasse, die alle Berechnungen verpackt und eine Historie speichert.

class PythagorasCalculator:
    def __init__(self):
        self.history = []

    def aufstellen(self, a: float, b: float) -> float:
        a = _validate_positive(a, "a")
        b = _validate_positive(b, "b")
        result = a * a + b * b
        self.history.append(f"a2 + b2 = {a}2 + {b}2 = {result}")
        return result

    def kontrolliere(self, a: float, b: float, c: float) -> bool:
        a = _validate_positive(a, "a")
        b = _validate_positive(b, "b")
        c = _validate_positive(c, "c")
        result = bool(pythagoras_lib.kontrolliere(a, b, c))
        self.history.append(f"a2 + b2 == c2  {a}2 + {b}2 = {c}2 {result}")
        return result

    def wurzel(self, a: float, b: float) -> float:
        a = _validate_positive(a, "a")
        b = _validate_positive(b, "b")
        result = pythagoras_lib.wurzel(a, b)
        self.history.append(f"√({a}2 + {b}2) = {result}")
        return result

    def get_history(self) -> list:
        return self.history.copy()

    def clear_history(self):
        self.history.clear()
    

3. Unit-Tests mit pytest

Die Tests überprüfen alle Funktionen und die Klasse auf Richtigkeit und Fehlerbehandlung.

# test_pythagoras.py

def test_negative_input():
    with pytest.raises(ValueError, match="a darf nicht negativ sein"):
        pythagoras.aufstellen(-1, 2)

def test_valid_calculations():
    assert pythagoras.aufstellen(3, 4) == 25.0
    assert pythagoras.kontrolliere(3, 4, 5) == True
    assert pythagoras.wurzel(3, 4) == 5.0

def test_calculator():
    calc = pythagoras.PythagorasCalculator()
    assert calc.aufstellen(3, 4) == 25.0
    assert calc.kontrolliere(3, 4, 5) == True
    assert calc.wurzel(3, 4) == 5.0
    assert calc.get_history() == []

def test_history():
    calc = pythagoras.PythagorasCalculator()
    calc.aufstellen(3, 4)
    calc.kontrolliere(3, 4, 5)
    assert len(calc.get_history()) == 2

def test_clear_history():
    calc = pythagoras.PythagorasCalculator()
    calc.aufstellen(3, 4)
    calc.clear_history()
    assert len(calc.get_history()) == 0
    

4. C-Quellcode: pythagoras.cpp

Der C-Quellcode wird kompiliert und wird als Python-Modul (.pyd) verwendet. Er exportiert die Funktionen über ctypes.

// pythagoras.cpp
// C-Quellcode wird kompiliert zu ein Python-Modul (pythagoras.pyd)

#include 

// Exportierte Funktionen für Python über ctypes
double aufstellen(double a, double b) {
    return a * a + b * b;
}

int kontrolliere(double a, double b, double c) {
    double a2 = a * a;
    double b2 = b * b;
    double c2 = c * c;
    return (abs(a2 + b2 - c2) < 1e-10) ? 1 : 0;
}

double wurzel(double a, double b) {
    return sqrt(a * a + b * b);
}

void ausgabe_pythagoras(double a, double b, double c) {
    printf("Pythagoras: %f2 + %f2 = %f2\n", a, b, c);
}
    

5. Build-Script: build.bat

Ein Windows-Bat-Script zum Kompilieren des C-Moduls mit gcc (MinGW).

@echo off
:: Kompiliere pythagoras.cpp zu ein Python-Modul (.pyd)

:: 1. Prüfe, ob MinGW (gcc) installiert ist
where gcc >nul 2>&1
if %errorlevel% neq 0 (
    echo  Fehler: MinGW (gcc) nicht gefunden!
    echo Bitte installiere MinGW 
    pause
    exit /b 1
)

:: 2. Erstelle den Ordner build/lib
if not exist build (
    mkdir build
)
if not exist build/lib (
    mkdir build/lib
)

:: 3. Kompiliere das Modul mit gcc
gcc -c pythagoras.cpp -o pythagoras.o
gcc -shared -fPIC -o build/lib/pythagoras.pyd pythagoras.o

echo Erfolgreich kompiliert: build/lib/pythagoras.pyd
pause
    

Ablauf: Wie wird das Projekt erstellt?

  1. Starte die Kommandozeile und navigiere zum Projektverzeichnis:
  2. cd pythagoras_project
  3. Führe das Build-Script aus:
  4. build.bat
  5. Ergebnis: Das Modul build/lib/pythagoras.pyd wird erstellt.
  6. Installiere pytest:
  7. pip install pytest
  8. Führe die Tests aus:
  9. python -m pytest test_pythagoras.py -v
  10. Ergebnis: Alle 7 Tests werden erfolgreich abgeschlossen.

Demo-Test: main.py

Ein einfaches Beispiel, wie das Modul verwendet wird.

# main.py

import pythagoras
import pytest

print("DEMOTEST: Pythagoras-Modul mit Fehlerbehandlung und Klasse")

# 1. Direkte Funktionen
print("\nFunktionen:")
print(f"a2 + b2 = {pythagoras.aufstellen(3, 4)}")
print(f"Ergebnis: {pythagoras.kontrolliere(3, 4, 5)}")
print(f"√(32 + 42) = {pythagoras.wurzel(3, 4):.2f}")

# 2. Klasse verwenden
print("\nKlasse PythagorasCalculator:")
calc = pythagoras.PythagorasCalculator()
calc.aufstellen(5, 12)
calc.kontrolliere(5, 12, 13)
calc.wurzel(5, 12)

print("Historie:")
for entry in calc.get_history():
    print(f"  -> {entry}")

# 3. Fehlerbehandlung
try:
    pythagoras.aufstellen(-1, 2)
except ValueError as e:
    print(f"Fehler erkannt: {e}")

# 4. Ausgabe
pythagoras.ausgabe_pythagoras(3, 4, 5)

print("\nDEMOTEST erfolgreich abgeschlossen!")
    

? Erfolgskriterien