Zum Inhalt springen
aviral gupta

// B3.5 · ca. 40 Min. · Einstieg

Projekt: eine Bibliothek zum Umrechnen von Einheiten

In diesem Projekt schreiben Sie eine kleine Bibliothek zum Umrechnen: dokumentierte Funktionen für Längen und Temperaturen, ValueError bei falscher Eingabe und ein convert() mit einer Rundungsoption, die nur per Schlüsselwort geht.

Lektion 5 von 5 in B3 Funktionen

Ende des Moduls

Danach können Sie

  • Argumente prüfen und falsche mit raise ValueError und klarer Meldung ablehnen
  • Einer Funktion Optionen mit Standardwert geben, die nur per Schlüsselwort gehen
  • Eine Aufgabe in kleine dokumentierte Funktionen zerlegen, die einander aufrufen
  1. Aufwärmen · Aufgabe 1 von 7

    Aufwärmen aus Lektion B3.4: Die Sortierung ist stabil. Was gibt das aus?

    units = ["km", "m", "cm"]
    print(sorted(units, key=len))
  2. Vorhersagen · Aufgabe 2 von 7

    Sagen Sie es voraus, bevor Sie weiterlesen: Das Programm gibt zuerst 30 aus. Was ist die letzte Zeile, die Python zeigt?

    def check_age(age):
        if age < 0:
            raise ValueError("age cannot be negative")
        return age
    
    print(check_age(30))
    print(check_age(-1))
    print("done")
  3. Üben · Aufgabe 3 von 7

    Ergänzen Sie das Schlüsselwort, damit eine unbekannte Einheit die Funktion mit einem ValueError beendet.

    def metres_per(unit):
        if unit == "m":
            return 1.0
        ____ ValueError("unknown unit: " + unit)
    ValueError("unknown unit: " + unit)
  4. Üben · Aufgabe 4 von 7

    def convert(value, from_unit, to_unit, *, digits=None): Welchen Aufruf lehnt Python ab?

  5. Üben · Aufgabe 5 von 7

    Bringen Sie die Schritte von convert_length(value, from_unit, to_unit) in die richtige Reihenfolge.

    1. 1.Die Meter durch die Meter pro to_unit teilen
    2. 2.value damit multiplizieren, um Meter zu erhalten
    3. 3.Nachschlagen, wie viele Meter eine from_unit sind
    4. 4.ValueError auslösen, wenn value negativ ist
    5. 5.Das Ergebnis zurückgeben
  6. Denksport · Aufgabe 6 von 7

    Knobelaufgabe. Umrechner arbeiten mit floats. Was gibt das aus?

    print(0.1 + 0.2 == 0.3, round(0.1 + 0.2, 2) == 0.3)
  7. Anwenden · Aufgabe 7 von 7

    Kleine Aufgabe. Ergänzen Sie die Bibliothek um Gewichte: grams_per(unit) für "g", "kg" und "t" (1 t sind 1.000.000 g) und convert_weight(value, from_unit, to_unit, *, digits=2). Lösen Sie ValueError aus für eine unbekannte Einheit und für ein negatives Gewicht. Geben Sie 1500 g in kg aus, 2 t in kg und 1 kg in g mit digits=0.

    Prüfen Sie Ihr Ergebnis anhand dieser Liste

Selbst programmieren

Lesen Sie das ausgearbeitete Beispiel und lösen Sie dann die Übungen. Ihr Code läuft in Ihrem Browser oder auf Ihrem Computer und wird nie hochgeladen.

Ausgearbeitetes Beispiel

Ein Zeitumrechner

Das ist das Muster des Projekts, hier für Zeitdauern. seconds_per kennt die Einheiten und löst für jede andere ValueError aus. convert_time prüft den Wert, rechnet über Sekunden und rundet mit einer Option digits, die nur per Schlüsselwort geht und standardmäßig 2 ist. Die def-Zeile ist auf drei Zeilen verteilt, damit sie unter 79 Zeichen bleibt; PEP 8 erlaubt das innerhalb von Klammern.

main.py

def seconds_per(unit: str) -> int:
    """Return how many seconds one unit is."""
    if unit == "s":
        return 1
    elif unit == "min":
        return 60
    elif unit == "h":
        return 3600
    elif unit == "d":
        return 86400
    raise ValueError("unknown time unit: " + unit)


def convert_time(
    value: float, from_unit: str, to_unit: str, *, digits: int = 2
) -> float:
    """Convert a duration between units, rounded to digits places."""
    if value < 0:
        raise ValueError("a duration cannot be negative")
    seconds = value * seconds_per(from_unit)
    return round(seconds / seconds_per(to_unit), digits)


print(convert_time(90, "min", "h"))
print(convert_time(1, "d", "min"))
print(convert_time(100, "s", "min"))
print(convert_time(100, "s", "min", digits=4))
print(convert_time.__doc__)

Ausführen mit

python main.py

Ausgabe

1.5
1440.0
1.67
1.6667
Convert a duration between units, rounded to digits places.
  • 90 Minuten sind 5400 Sekunden, und 5400 / 3600 ist 1.5 Stunden.
  • 100 Sekunden sind 1.666… Minuten: 1.67 mit dem Standard digits=2, 1.6667 mit digits=4.
  • convert_time(-5, "s", "min") oder convert_time(1, "s", "week") würden mit einem ValueError enden.
  • Der Docstring ist einzeilig, also gibt __doc__ genau diese Zeile aus.
Ändern und ausführen

Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.

Beim ersten Ausführen lädt Ihr Browser Python herunter (bis zu 6.5 MB) und speichert es im Cache. Ihr Code bleibt auf Ihrem Gerät.

Übungen

Übung 1 von 3

Schritt 1: Längen

Beginnen Sie die Bibliothek mit Längen. metres_per(unit) gibt zurück, wie viele Meter eine Einheit sind: mm 0.001, cm 0.01, m 1.0, km 1000.0, und löst für alles andere ValueError("unknown length unit: " + unit) aus. convert_length(value, from_unit, to_unit) löst für einen negativen Wert ValueError aus und rechnet dann über Meter um. Die Tests vergleichen auf 6 Stellen gerundet.

Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.

Beim ersten Ausführen lädt Ihr Browser Python herunter (bis zu 6.5 MB) und speichert es im Cache. Ihr Code bleibt auf Ihrem Gerät.

Hinweise
  1. Hinweis 1

    Schreiben Sie metres_per als Kette aus if und elif mit einem return je Einheit, und setzen Sie raise ValueError(…) hinter die Kette.

  2. Hinweis 2

    Prüfen Sie in convert_length zuerst if value < 0: und lösen Sie dann den Fehler aus.

  3. Hinweis 3

    Danach: return value * metres_per(from_unit) / metres_per(to_unit).

Eine Lösung zeigen

Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.

LENGTH_UNITS = ["mm", "cm", "m", "km"]


def metres_per(unit: str) -> float:
    """Return how many metres one unit is."""
    if unit == "mm":
        return 0.001
    elif unit == "cm":
        return 0.01
    elif unit == "m":
        return 1.0
    elif unit == "km":
        return 1000.0
    raise ValueError("unknown length unit: " + unit)


def convert_length(value: float, from_unit: str, to_unit: str) -> float:
    """Convert a length from one unit to another."""
    if value < 0:
        raise ValueError("a length cannot be negative")
    return value * metres_per(from_unit) / metres_per(to_unit)


print(convert_length(2.5, "km", "m"))
Auf dem eigenen Computer ausführen

Installieren Sie Python 3.14 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.

main.py

LENGTH_UNITS = ["mm", "cm", "m", "km"]


def metres_per(unit: str) -> float:
    """Return how many metres one unit is."""
    if unit == "m":
        return 1.0
    # Add mm, cm and km, and raise ValueError for any other unit.
    return 1.0


def convert_length(value: float, from_unit: str, to_unit: str) -> float:
    """Convert a length from one unit to another."""
    # Raise ValueError for a negative value, then convert via metres.
    return value


print(convert_length(2.5, "km", "m"))

test_main.py

from main import convert_length


def test_km_to_m():
    """2.5 km sind 2500 m"""
    got = convert_length(2.5, "km", "m")
    assert round(got, 6) == 2500.0, f"convert_length(2.5, 'km', 'm') lieferte {got!r}, erwartet: 2500.0"


def test_cm_to_m():
    """250 cm sind 2.5 m"""
    got = convert_length(250, "cm", "m")
    assert round(got, 6) == 2.5, f"convert_length(250, 'cm', 'm') lieferte {got!r}, erwartet: 2.5"


def test_mm_to_cm():
    """5 mm sind 0.5 cm"""
    got = convert_length(5, "mm", "cm")
    assert round(got, 6) == 0.5, f"convert_length(5, 'mm', 'cm') lieferte {got!r}, erwartet: 0.5"


def test_same_unit():
    """7 m sind 7 m"""
    got = convert_length(7, "m", "m")
    assert round(got, 6) == 7.0, f"convert_length(7, 'm', 'm') lieferte {got!r}, erwartet: 7.0"


def test_unknown_unit():
    """Eine unbekannte Einheit löst ValueError aus"""
    try:
        got = convert_length(3, "m", "miles")
    except ValueError:
        return
    raise AssertionError(f"convert_length(3, 'm', 'miles') lieferte {got!r} statt einen ValueError auszulösen")


def test_negative_length():
    """Eine negative Länge löst ValueError aus"""
    try:
        got = convert_length(-1, "m", "cm")
    except ValueError:
        return
    raise AssertionError(f"convert_length(-1, 'm', 'cm') lieferte {got!r} statt einen ValueError auszulösen")

Unter macOS und Linux tippen Sie python3, wo in diesen Befehlen python steht, wie in der ersten Lektion.

Programm ausführen:

python main.py

Prüfungen ausführen (learnrun.py muss im selben Ordner liegen):

python learnrun.py test
learnrun.py herunterladen

Übung 2 von 3

Schritt 2: Temperaturen

Ergänzen Sie Temperaturen in "C", "F" und "K". Schreiben Sie to_kelvin(value, unit) und from_kelvin(kelvin, unit): K = C + 273.15 und C = (F - 32) * 5 / 9. Beide lösen für eine unbekannte Einheit ValueError aus. convert_temperature(value, from_unit, to_unit) rechnet in Kelvin um, löst unter 0 K ValueError aus und rechnet von Kelvin in die Zieleinheit. Schritt 1 steht schon in main.py.

Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.

Beim ersten Ausführen lädt Ihr Browser Python herunter (bis zu 6.5 MB) und speichert es im Cache. Ihr Code bleibt auf Ihrem Gerät.

Hinweise
  1. Hinweis 1

    to_kelvin: K gibt value zurück, C gibt value + 273.15, F gibt (value - 32) * 5 / 9 + 273.15, alles andere löst den Fehler aus.

  2. Hinweis 2

    from_kelvin kehrt das um: C ist kelvin - 273.15, F ist (kelvin - 273.15) * 9 / 5 + 32.

  3. Hinweis 3

    convert_temperature: kelvin = to_kelvin(value, from_unit); if kelvin < 0: raise ValueError(…); return from_kelvin(kelvin, to_unit).

Eine Lösung zeigen

Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.

LENGTH_UNITS = ["mm", "cm", "m", "km"]


def metres_per(unit: str) -> float:
    """Return how many metres one unit is."""
    if unit == "mm":
        return 0.001
    elif unit == "cm":
        return 0.01
    elif unit == "m":
        return 1.0
    elif unit == "km":
        return 1000.0
    raise ValueError("unknown length unit: " + unit)


def convert_length(value: float, from_unit: str, to_unit: str) -> float:
    """Convert a length from one unit to another."""
    if value < 0:
        raise ValueError("a length cannot be negative")
    return value * metres_per(from_unit) / metres_per(to_unit)


TEMPERATURE_UNITS = ["C", "F", "K"]


def to_kelvin(value: float, unit: str) -> float:
    """Return the temperature in kelvin."""
    if unit == "K":
        return value
    elif unit == "C":
        return value + 273.15
    elif unit == "F":
        return (value - 32) * 5 / 9 + 273.15
    raise ValueError("unknown temperature unit: " + unit)


def from_kelvin(kelvin: float, unit: str) -> float:
    """Return a temperature given in kelvin in another unit."""
    if unit == "K":
        return kelvin
    elif unit == "C":
        return kelvin - 273.15
    elif unit == "F":
        return (kelvin - 273.15) * 9 / 5 + 32
    raise ValueError("unknown temperature unit: " + unit)


def convert_temperature(value: float, from_unit: str, to_unit: str) -> float:
    """Convert a temperature between C, F and K."""
    kelvin = to_kelvin(value, from_unit)
    if kelvin < 0:
        raise ValueError("below absolute zero")
    return from_kelvin(kelvin, to_unit)


print(convert_temperature(100, "C", "F"))
Auf dem eigenen Computer ausführen

Installieren Sie Python 3.14 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.

main.py

LENGTH_UNITS = ["mm", "cm", "m", "km"]


def metres_per(unit: str) -> float:
    """Return how many metres one unit is."""
    if unit == "mm":
        return 0.001
    elif unit == "cm":
        return 0.01
    elif unit == "m":
        return 1.0
    elif unit == "km":
        return 1000.0
    raise ValueError("unknown length unit: " + unit)


def convert_length(value: float, from_unit: str, to_unit: str) -> float:
    """Convert a length from one unit to another."""
    if value < 0:
        raise ValueError("a length cannot be negative")
    return value * metres_per(from_unit) / metres_per(to_unit)


TEMPERATURE_UNITS = ["C", "F", "K"]


def convert_temperature(value: float, from_unit: str, to_unit: str) -> float:
    """Convert a temperature between C, F and K."""
    # Step 2: convert to kelvin first, refuse anything below 0 K,
    # then convert from kelvin to the target unit.
    return value


print(convert_temperature(100, "C", "F"))

test_main.py

from main import convert_temperature


def test_c_to_f():
    """100 C sind 212 F"""
    got = convert_temperature(100, "C", "F")
    assert round(got, 6) == 212.0, f"convert_temperature(100, 'C', 'F') lieferte {got!r}, erwartet: 212.0"


def test_f_to_c():
    """32 F sind 0 C"""
    got = convert_temperature(32, "F", "C")
    assert round(got, 6) == 0.0, f"convert_temperature(32, 'F', 'C') lieferte {got!r}, erwartet: 0.0"


def test_kelvin():
    """0 C sind 273.15 K, und 0 K sind -273.15 C"""
    got = convert_temperature(0, "C", "K"), convert_temperature(0, "K", "C")
    assert (round(got[0], 6), round(got[1], 6)) == (273.15, -273.15), f"convert_temperature(0, 'C', 'K') und convert_temperature(0, 'K', 'C') lieferten {got!r}"


def test_minus_forty():
    """-40 C sind -40 F"""
    got = convert_temperature(-40, "C", "F")
    assert round(got, 6) == -40.0, f"convert_temperature(-40, 'C', 'F') lieferte {got!r}, erwartet: -40.0"


def test_below_absolute_zero():
    """-300 C und -1 K lösen ValueError aus"""
    for value, unit in [(-300, "C"), (-1, "K")]:
        try:
            got = convert_temperature(value, unit, "F")
        except ValueError:
            continue
        raise AssertionError(f"convert_temperature({value}, {unit!r}, 'F') lieferte {got!r} statt einen ValueError auszulösen")


def test_unknown_unit():
    """Eine unbekannte Einheit löst ValueError aus"""
    try:
        got = convert_temperature(20, "C", "X")
    except ValueError:
        return
    raise AssertionError(f"convert_temperature(20, 'C', 'X') lieferte {got!r} statt einen ValueError auszulösen")

Unter macOS und Linux tippen Sie python3, wo in diesen Befehlen python steht, wie in der ersten Lektion.

Programm ausführen:

python main.py

Prüfungen ausführen (learnrun.py muss im selben Ordner liegen):

python learnrun.py test
learnrun.py herunterladen

Übung 3 von 3

Schritt 3: ein convert() für alles

Vollenden Sie die Bibliothek mit convert(value, from_unit, to_unit, *, digits=None). Stehen beide Einheiten in LENGTH_UNITS, nutzen Sie convert_length; stehen beide in TEMPERATURE_UNITS, nutzen Sie convert_temperature; sonst lösen Sie ValueError("cannot convert " + from_unit + " to " + to_unit) aus. Ist digits nicht None, runden Sie das Ergebnis. Annotieren Sie digits als int | None, und geben Sie convert einen Docstring.

Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.

Beim ersten Ausführen lädt Ihr Browser Python herunter (bis zu 6.5 MB) und speichert es im Cache. Ihr Code bleibt auf Ihrem Gerät.

Hinweise
  1. Hinweis 1

    from_unit in LENGTH_UNITS ist True, wenn die Einheit in der Liste steht; verbinden Sie zwei solche Tests mit and.

  2. Hinweis 2

    Speichern Sie das Ergebnis von convert_length oder convert_temperature in einer Variablen, und lösen Sie im else-Zweig ValueError aus.

  3. Hinweis 3

    Ergänzen Sie *, digits: int | None = None in den Parametern, dann: if digits is not None: result = round(result, digits).

Eine Lösung zeigen

Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.

LENGTH_UNITS = ["mm", "cm", "m", "km"]


def metres_per(unit: str) -> float:
    """Return how many metres one unit is."""
    if unit == "mm":
        return 0.001
    elif unit == "cm":
        return 0.01
    elif unit == "m":
        return 1.0
    elif unit == "km":
        return 1000.0
    raise ValueError("unknown length unit: " + unit)


def convert_length(value: float, from_unit: str, to_unit: str) -> float:
    """Convert a length from one unit to another."""
    if value < 0:
        raise ValueError("a length cannot be negative")
    return value * metres_per(from_unit) / metres_per(to_unit)


TEMPERATURE_UNITS = ["C", "F", "K"]


def to_kelvin(value: float, unit: str) -> float:
    """Return the temperature in kelvin."""
    if unit == "K":
        return value
    elif unit == "C":
        return value + 273.15
    elif unit == "F":
        return (value - 32) * 5 / 9 + 273.15
    raise ValueError("unknown temperature unit: " + unit)


def from_kelvin(kelvin: float, unit: str) -> float:
    """Return a temperature given in kelvin in another unit."""
    if unit == "K":
        return kelvin
    elif unit == "C":
        return kelvin - 273.15
    elif unit == "F":
        return (kelvin - 273.15) * 9 / 5 + 32
    raise ValueError("unknown temperature unit: " + unit)


def convert_temperature(value: float, from_unit: str, to_unit: str) -> float:
    """Convert a temperature between C, F and K."""
    kelvin = to_kelvin(value, from_unit)
    if kelvin < 0:
        raise ValueError("below absolute zero")
    return from_kelvin(kelvin, to_unit)


def convert(
    value: float, from_unit: str, to_unit: str, *, digits: int | None = None
) -> float:
    """Convert value between two units of the same kind.

    Lengths: mm, cm, m, km. Temperatures: C, F, K. With digits,
    the result is rounded to that many decimal places.
    """
    if from_unit in LENGTH_UNITS and to_unit in LENGTH_UNITS:
        result = convert_length(value, from_unit, to_unit)
    elif from_unit in TEMPERATURE_UNITS and to_unit in TEMPERATURE_UNITS:
        result = convert_temperature(value, from_unit, to_unit)
    else:
        raise ValueError("cannot convert " + from_unit + " to " + to_unit)
    if digits is not None:
        result = round(result, digits)
    return result


print(convert(1, "km", "m"))
print(convert(100, "C", "F", digits=1))
Auf dem eigenen Computer ausführen

Installieren Sie Python 3.14 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.

main.py

LENGTH_UNITS = ["mm", "cm", "m", "km"]


def metres_per(unit: str) -> float:
    """Return how many metres one unit is."""
    if unit == "mm":
        return 0.001
    elif unit == "cm":
        return 0.01
    elif unit == "m":
        return 1.0
    elif unit == "km":
        return 1000.0
    raise ValueError("unknown length unit: " + unit)


def convert_length(value: float, from_unit: str, to_unit: str) -> float:
    """Convert a length from one unit to another."""
    if value < 0:
        raise ValueError("a length cannot be negative")
    return value * metres_per(from_unit) / metres_per(to_unit)


TEMPERATURE_UNITS = ["C", "F", "K"]


def to_kelvin(value: float, unit: str) -> float:
    """Return the temperature in kelvin."""
    if unit == "K":
        return value
    elif unit == "C":
        return value + 273.15
    elif unit == "F":
        return (value - 32) * 5 / 9 + 273.15
    raise ValueError("unknown temperature unit: " + unit)


def from_kelvin(kelvin: float, unit: str) -> float:
    """Return a temperature given in kelvin in another unit."""
    if unit == "K":
        return kelvin
    elif unit == "C":
        return kelvin - 273.15
    elif unit == "F":
        return (kelvin - 273.15) * 9 / 5 + 32
    raise ValueError("unknown temperature unit: " + unit)


def convert_temperature(value: float, from_unit: str, to_unit: str) -> float:
    """Convert a temperature between C, F and K."""
    kelvin = to_kelvin(value, from_unit)
    if kelvin < 0:
        raise ValueError("below absolute zero")
    return from_kelvin(kelvin, to_unit)


def convert(value: float, from_unit: str, to_unit: str) -> float:
    """Convert value between two units of the same kind."""
    # Step 3: pick convert_length or convert_temperature, refuse mixed
    # kinds, and add a keyword-only option digits for rounding.
    return value


print(convert(1, "km", "m"))

test_main.py

from main import convert


def test_length():
    """convert(1, "km", "m") ist 1000"""
    got = convert(1, "km", "m")
    assert round(got, 6) == 1000.0, f"convert(1, 'km', 'm') lieferte {got!r}, erwartet: 1000.0"


def test_temperature():
    """convert(100, "C", "F") ist 212"""
    got = convert(100, "C", "F")
    assert round(got, 6) == 212.0, f"convert(100, 'C', 'F') lieferte {got!r}, erwartet: 212.0"


def test_digits():
    """digits=1 rundet 123.456 cm auf 123.5"""
    got = convert(1.23456, "m", "cm", digits=1)
    assert got == 123.5, f"convert(1.23456, 'm', 'cm', digits=1) lieferte {got!r}, erwartet: 123.5"


def test_mixed_kinds():
    """Eine Länge wird keine Temperatur"""
    try:
        got = convert(1, "m", "C")
    except ValueError:
        return
    raise AssertionError(f"convert(1, 'm', 'C') lieferte {got!r} statt einen ValueError auszulösen")


def test_digits_keyword_only():
    """digits muss per Schlüsselwort kommen"""
    try:
        got = convert(1.23456, "m", "cm", 1)
    except TypeError:
        return
    raise AssertionError(f"convert(1.23456, 'm', 'cm', 1) lieferte {got!r}; digits sollte nur per Schlüsselwort gehen")


def test_docstring():
    """convert hat einen Docstring"""
    assert convert.__doc__, "convert hat keinen Docstring"

Unter macOS und Linux tippen Sie python3, wo in diesen Befehlen python steht, wie in der ersten Lektion.

Programm ausführen:

python main.py

Prüfungen ausführen (learnrun.py muss im selben Ordner liegen):

python learnrun.py test
learnrun.py herunterladen

Häufige Fehler

Eine Einheit, die die Bibliothek nicht kennt

def metres_per(unit: str) -> float:
    """Return how many metres one unit is."""
    if unit == "m":
        return 1.0
    elif unit == "km":
        return 1000.0
    raise ValueError("unknown length unit: " + unit)


def convert_length(value: float, from_unit: str, to_unit: str) -> float:
    """Convert a length from one unit to another."""
    return value * metres_per(from_unit) / metres_per(to_unit)


print(convert_length(3, "m", "miles"))

Was Python ausgibt

ValueError: unknown length unit: miles

Warum, und die Lösung

Hier arbeitet die Prüfung wie gewollt: Der Traceback führt vom Aufruf bis zur raise-Zeile in metres_per, und die letzte Zeile trägt Ihre Meldung. Korrigieren Sie den Aufruf, oder ergänzen Sie die Einheit in metres_per. Eine Meldung, die den falschen Wert nennt, macht die Suche kurz.

Eine Schlüsselwort-Option nach Position übergeben

def convert(value: float, factor: float, *, digits: int = 2) -> float:
    """Multiply value by factor and round the result."""
    return round(value * factor, digits)


print(convert(1.23456, 100, 0))

Was Python ausgibt

TypeError: convert() takes 2 positional arguments but 3 were given

Warum, und die Lösung

digits steht hinter dem * und muss genannt werden: convert(1.23456, 100, digits=0). Genau darum geht es bei solchen Optionen: Eine nackte 0 im Aufruf sagt nichts darüber, was sie steuert.

Einen String statt einer Ausnahme auslösen

def metres_per(unit: str) -> float:
    """Return how many metres one unit is."""
    if unit == "m":
        return 1.0
    raise "unknown length unit: " + unit


print(metres_per("ft"))

Was Python ausgibt

TypeError: exceptions must derive from BaseException

Warum, und die Lösung

raise braucht eine Ausnahme, keinen einfachen String. Verpacken Sie die Meldung: raise ValueError("unknown length unit: " + unit). mypy meldet diesen Fehler schon, bevor das Programm läuft.

Python im Browser: Pyodide 314.0.7, MPL-2.0. Lizenz und Quellcode

Abschlussquiz

5 Fragen, ohne Hinweise. Ab 80 % ist die Lektion abgeschlossen.

Erledigen Sie zuerst alle Aufgaben oben, um das Abschlussquiz freizuschalten.

Problem melden

Etwas ist falsch oder unklar? Beschreiben Sie es kurz, dann wird es geprüft und korrigiert.

#

Mindestens 20 Zeichen.

Nur, wenn Sie eine Antwort wünschen.

Kernideen

raise ValueError lehnt falsche Eingaben ab

Eine Funktion sollte nicht still Unsinn zurückgeben. Hat ein Argument den richtigen Typ, aber einen unsinnigen Wert, etwa die Einheit "miles" in einem metrischen Rechner oder -300 °C, dann schreiben Sie raise ValueError("unknown length unit: miles"). raise beendet die Funktion sofort, wie return, aber statt eines Ergebnisses erhält der Aufrufer einen Fehler mit Ihrer Meldung. Fängt ihn niemand ab, endet das Programm mit ValueError: unknown length unit: miles. Wie ein Aufrufer ihn abfängt, zeigt ein späteres Modul.

Optionen nur per Schlüsselwort

Pflichtangaben kommen zuerst und nach Position: der Wert und die beiden Einheiten. Optionen, die nur die Form des Ergebnisses ändern, stehen hinter einem * und haben einen Standardwert: def convert(value, from_unit, to_unit, *, digits=None):. Aufrufer müssen dann digits=1 schreiben; convert(5, "m", "cm", 1) wird abgelehnt, und niemand rätselt, was die 1 bedeutet. None als Standardwert heißt „nicht angegeben“: if digits is not None: wird gerundet. Die Annotation int | None heißt „ein int oder None“.

Kleine Funktionen, jede mit einer Aufgabe

Die Bibliothek besteht aus kleinen Teilen. metres_per(unit) kennt die Längeneinheiten und sonst nichts; convert_length nutzt sie zweimal, einmal je Einheit. to_kelvin und from_kelvin tun dasselbe für Temperaturen, so läuft jede Umrechnung über eine gemeinsame Einheit. convert() oben wählt nur, welcher Teil aufgerufen wird. Jede Funktion hat Docstring und Annotationen und lässt sich allein testen. Ergebnisse sind floats, deshalb vergleichen die Tests gerundet: 0.1 + 0.2 ist nicht genau 0.3.

Quellen

Zuletzt geprüft am 29. September 2026