Zum Inhalt springen
aviral gupta

// B3.4 · ca. 30 Min. · Einstieg

Lambdas, Docstrings, Annotationen und PEP 8

Nach dieser Lektion sortieren Sie mit einem Lambda als Schlüssel, dokumentieren eine Funktion mit passendem Docstring und Annotationen und benennen und gestalten Code so, wie PEP 8 es verlangt.

Lektion 4 von 5 in B3 Funktionen

Danach können Sie

  • Ein Lambda schreiben und als key an sorted() übergeben
  • Docstrings nach den Konventionen schreiben sowie Annotationen setzen und lesen
  • PEP 8 anwenden: Namen in lowercase_with_underscores, 4 Leerzeichen Einrückung, 79 Zeichen pro Zeile, Leerzeichen
  1. Aufwärmen · Aufgabe 1 von 7

    Aufwärmen aus Lektion B3.3: Was gibt das aus?

    def f(*args, **kwargs):
        print(len(args), len(kwargs))
    
    f(1, 2, x=3)
  2. Vorhersagen · Aufgabe 2 von 7

    Sagen Sie es vorher, bevor Sie weiterlesen: Der Schlüssel ist ein Lambda, das den letzten Buchstaben nimmt. Was gibt das aus?

    words = ["kiwi", "fig", "banana", "apple"]
    print(sorted(words, key=lambda w: w[-1]))
  3. Üben · Aufgabe 3 von 7

    Setzen Sie das Schlüsselwort ein, damit die Paare nach Punkten sortiert werden, die niedrigste zuerst.

    scores = [["ann", 82], ["bo", 95], ["cy", 78]]
    print(sorted(scores, key=____ pair: pair[1]))
    key= pair: pair[1]
  4. Üben · Aufgabe 4 von 7

    Was gibt das aus?

    def greet(name: str, times: int = 1) -> str:
        return name * times
    
    print(greet.__annotations__)
  5. Üben · Aufgabe 5 von 7

    Ordnen Sie jedem Teil eines Programms die PEP-8-Regel dafür zu.

  6. Denksport · Aufgabe 6 von 7

    Knobelaufgabe. Die Annotation sagt int, übergeben wird ein String. Was gibt das aus?

    def double(n: int) -> int:
        return n * 2
    
    print(double("ab"))
  7. Anwenden · Aufgabe 7 von 7

    Mini-Aufgabe. Schreiben Sie longest_first(words: list[str]) -> list[str], das die Wörter vom längsten zum kürzesten sortiert zurückgibt, mit sorted, einem key und reverse=True. Geben Sie ihr einen einzeiligen Docstring. Geben Sie das Ergebnis für ["fig", "banana", "kiwi", "plum"] aus und danach ihr __doc__.

    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

Eine Teamliste sortieren

Ein einfaches sorted stellt Großbuchstaben vor Kleinbuchstaben, also kommt "Bo" vor "ada". sort_names behebt das mit einem Lambda als Schlüssel, das kleingeschriebene Namen vergleicht; name.lower() liefert den Namen in Kleinbuchstaben. Mit by_length=True sortiert es noch einmal nach Länge, und die stabile Sortierung hält gleich lange Namen alphabetisch. Die Funktion ist annotiert und hat einen mehrzeiligen Docstring.

main.py

def sort_names(names: list[str], *, by_length: bool = False) -> list[str]:
    """Return the names sorted alphabetically, ignoring case.

    With by_length=True, shorter names come first; names of the
    same length keep their alphabetical order.
    """
    ordered = sorted(names, key=lambda name: name.lower())
    if by_length:
        ordered = sorted(ordered, key=len)
    return ordered


team = ["maya", "Bo", "leon", "ada", "Christopher"]
print(sorted(team))
print(sort_names(team))
print(sort_names(team, by_length=True))
print(sort_names.__annotations__)
print(sort_names.__doc__)

Ausführen mit

python main.py

Ausgabe

['Bo', 'Christopher', 'ada', 'leon', 'maya']
['ada', 'Bo', 'Christopher', 'leon', 'maya']
['Bo', 'ada', 'leon', 'maya', 'Christopher']
{'names': list[str], 'by_length': <class 'bool'>, 'return': list[str]}
Return the names sorted alphabetically, ignoring case.

With by_length=True, shorter names come first; names of the
same length keep their alphabetical order.
  • Ohne Schlüssel sortiert jeder Großbuchstabe vor jedem Kleinbuchstaben.
  • key=len braucht kein Lambda: Jede Funktion mit einem Argument kann der Schlüssel sein.
  • leon und maya sind gleich lang und bleiben alphabetisch, weil die Sortierung stabil ist.
  • Der Docstring behält seine leere zweite Zeile; Python entfernt die Einrückung der späteren Zeilen.
Ä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 2

Sortieren mit Schlüsseln

Vervollständigen Sie zwei Funktionen. sort_by_last_letter(words) gibt die Wörter nach ihrem letzten Buchstaben sortiert zurück, mit einem Lambda als Schlüssel. sort_by_length(words, *, longest_first=False) sortiert sie nach Länge, die kürzesten zuerst, oder die längsten zuerst bei longest_first=True. Gleich lange Wörter behalten ihre Reihenfolge. Beide liefern neue Listen und lassen das Argument unverändert.

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

    sorted(words, key=…) liefert eine neue sortierte Liste und lässt words in Ruhe.

  2. Hinweis 2

    Für den letzten Buchstaben ist der Schlüssel lambda word: word[-1]. Für die Länge reicht key=len.

  3. Hinweis 3

    Reichen Sie den Schalter direkt weiter: sorted(words, key=len, reverse=longest_first).

Eine Lösung zeigen

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

def sort_by_last_letter(words: list[str]) -> list[str]:
    """Return the words sorted by their last letter."""
    return sorted(words, key=lambda word: word[-1])


def sort_by_length(words: list[str], *, longest_first: bool = False) -> list[str]:
    """Return the words sorted by length, shortest first by default."""
    return sorted(words, key=len, reverse=longest_first)


print(sort_by_last_letter(["kiwi", "fig", "banana", "apple"]))
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

def sort_by_last_letter(words: list[str]) -> list[str]:
    """Return the words sorted by their last letter."""
    return list(words)  # sort them instead


def sort_by_length(words: list[str], *, longest_first: bool = False) -> list[str]:
    """Return the words sorted by length, shortest first by default."""
    return list(words)  # sort them instead


print(sort_by_last_letter(["kiwi", "fig", "banana", "apple"]))

test_main.py

from main import sort_by_last_letter, sort_by_length


def test_last_letter():
    """Nach dem letzten Buchstaben sortiert"""
    got = sort_by_last_letter(["kiwi", "fig", "banana", "apple"])
    assert got == ["banana", "apple", "fig", "kiwi"], f"sort_by_last_letter(['kiwi', 'fig', 'banana', 'apple']) lieferte {got!r}"


def test_shortest_first():
    """sort_by_length stellt das kürzeste Wort nach vorn"""
    got = sort_by_length(["pear", "fig", "banana"])
    assert got == ["fig", "pear", "banana"], f"sort_by_length(['pear', 'fig', 'banana']) lieferte {got!r}, erwartet: ['fig', 'pear', 'banana']"


def test_longest_first():
    """longest_first=True kehrt die Reihenfolge um"""
    got = sort_by_length(["pear", "fig", "banana"], longest_first=True)
    assert got == ["banana", "pear", "fig"], f"sort_by_length(['pear', 'fig', 'banana'], longest_first=True) lieferte {got!r}"


def test_equal_lengths_keep_order():
    """Gleich lange Wörter behalten ihre Reihenfolge"""
    got = sort_by_length(["bb", "aa", "c"])
    assert got == ["c", "bb", "aa"], f"sort_by_length(['bb', 'aa', 'c']) lieferte {got!r}, erwartet: ['c', 'bb', 'aa']"


def test_argument_unchanged():
    """Die übergebene Liste bleibt unverändert"""
    words = ["kiwi", "fig"]
    sort_by_length(words)
    assert words == ["kiwi", "fig"], f"nach sort_by_length(words) ist words {words!r}; verwenden Sie sorted(), das eine neue Liste liefert"

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 2

Eine Funktion aufräumen

calc_total funktioniert, verstößt aber gegen PEP 8 und ist nicht dokumentiert. Benennen Sie die Parameter in prices und tax_rate um, rücken Sie mit 4 Leerzeichen ein, geben Sie jeder Anweisung eine eigene Zeile und setzen Sie Leerzeichen um Operatoren. Ergänzen Sie einen einzeiligen Docstring und Annotationen: prices ist list[float], tax_rate ist float mit Standardwert 0.19, zurück kommt ein float. Das Ergebnis muss gleich bleiben.

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

    Beginnen Sie mit der def-Zeile: def calc_total(prices: list[float], tax_rate: float = 0.19) -> float:. PEP 8 will hier Leerzeichen um das =, weil der Parameter annotiert ist.

  2. Hinweis 2

    Teilen Sie for p in Prices:t=t+p in eine for-Zeile und eine eingerückte Rumpfzeile und verwenden Sie klare Namen: total und price.

  3. Hinweis 3

    Der Docstring steht direkt unter der def-Zeile, um 4 Leerzeichen eingerückt, zum Beispiel """Return the sum of the prices plus tax."""

Eine Lösung zeigen

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

def calc_total(prices: list[float], tax_rate: float = 0.19) -> float:
    """Return the sum of the prices plus tax."""
    total = 0.0
    for price in prices:
        total = total + price
    return total + total * tax_rate


print(calc_total([10, 20]))
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

def calc_total(Prices,Tax_Rate=0.19):
  t=0
  for p in Prices:t=t+p
  return t+t*Tax_Rate


print(calc_total([10, 20]))

test_main.py

from main import calc_total


def test_result_unchanged():
    """calc_total([10, 20]) ist weiter 35.7"""
    got = calc_total([10, 20])
    assert round(got, 2) == 35.7, f"calc_total([10, 20]) lieferte {got!r}, erwartet: 35.7"


def test_tax_rate_keyword():
    """Der Parameter heißt tax_rate"""
    got = calc_total([10.0], tax_rate=0.0)
    assert got == 10.0, f"calc_total([10.0], tax_rate=0.0) lieferte {got!r}, erwartet: 10.0"


def test_docstring():
    """Es gibt einen Docstring: vorn ein Großbuchstabe, hinten ein Punkt"""
    doc = calc_total.__doc__
    assert doc, "calc_total hat keinen Docstring"
    first = doc.strip().splitlines()[0]
    assert first[0].isupper() and first.endswith("."), f"die erste Zeile des Docstrings ist {first!r}"


def test_annotations():
    """prices, tax_rate und der Rückgabewert sind annotiert"""
    names = sorted(calc_total.__annotations__)
    assert names == ["prices", "return", "tax_rate"], f"calc_total.__annotations__ hat die Schlüssel {names!r}"
    assert calc_total.__annotations__["return"] is float, "die Rückgabe-Annotation sollte float sein"


def test_four_space_indent():
    """Jede eingerückte Zeile verwendet ein Vielfaches von 4 Leerzeichen"""
    with open("main.py", encoding="utf-8") as f:
        lines = f.read().splitlines()
    bad = [line for line in lines if line.startswith(" ") and (len(line) - len(line.lstrip(" "))) % 4 != 0]
    assert not bad, f"diese Zeilen sind nicht um ein Vielfaches von 4 Leerzeichen eingerückt: {bad!r}"

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

return in einem Lambda

words = ["kiwi", "fig", "banana"]
print(sorted(words, key=lambda w: return len(w)))

Was Python ausgibt

SyntaxError: invalid syntax

Warum, und die Lösung

Der Rumpf eines Lambdas ist ein einziger Ausdruck, und sein Wert wird automatisch zurückgegeben. return ist eine Anweisung und dort nicht erlaubt. Schreiben Sie lambda w: len(w) oder einfach key=len.

Die Schlüsselfunktion aufrufen, statt sie zu übergeben

words = ["kiwi", "fig", "banana"]
print(sorted(words, key=len()))

Was Python ausgibt

TypeError: len() takes exactly one argument (0 given)

Warum, und die Lösung

key braucht die Funktion selbst, die sorted für jedes Element aufruft. len() ruft len sofort auf, ohne Argument. Übergeben Sie den Namen ohne Klammern: key=len.

__annotations__ falsch schreiben

def greet(name: str) -> str:
    return "Hello, " + name

print(greet.__annotation__)

Was Python ausgibt

AttributeError: 'function' object has no attribute '__annotation__'

Warum, und die Lösung

Das Attribut heißt __annotations__, im Plural, mit zwei Unterstrichen auf jeder Seite. Python 3.14 ergänzt die Meldung um einen Vorschlag: Did you mean: '__annotations__'?

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

lambda erzeugt eine kleine Funktion an Ort und Stelle

lambda word: len(word) ist eine Funktion mit einem Parameter, word, die len(word) zurückgibt. Der Rumpf ist ein einziger Ausdruck: kein return, keine Anweisungen. Hauptzweck ist, eine kleine Funktion an eine andere zu übergeben. sorted(words, key=lambda word: word[-1]) ruft den Schlüssel einmal pro Element auf und sortiert nach den Ergebnissen, hier den letzten Buchstaben. reverse=True kehrt die Reihenfolge um. Die Sortierung ist stabil: Elemente mit gleichem Schlüssel behalten ihre Reihenfolge. PEP 8 sagt: Wollen Sie ein Lambda benennen, schreiben Sie ein def.

Docstrings und Annotationen

Die erste Zeile eines Docstrings ist eine kurze Zusammenfassung, die mit einem Großbuchstaben beginnt und mit einem Punkt endet. Ein längerer Docstring geht nach einer Leerzeile weiter. Annotationen dokumentieren Typen: def greet(name: str, times: int = 1) -> str:. Sie stehen in greet.__annotations__, aber Python prüft sie zur Laufzeit nicht: greet(5) läuft, bis etwas scheitert. Werkzeuge wie mypy lesen sie und melden Fehler vor dem Start; die Prüfungen auf dieser Seite lassen mypy über jede Lösung laufen.

PEP 8 in fünf Regeln

PEP 8 ist der Stilleitfaden, dem die meisten Python-Projekte folgen. Rücken Sie mit 4 Leerzeichen ein, nie mit Tabs. Halten Sie Zeilen bei höchstens 79 Zeichen. Benennen Sie Funktionen und Variablen in lowercase_with_underscores, Klassen in CapWords wie ShoppingCart und Konstanten in UPPER_CASE. Setzen Sie zwei Leerzeilen um Funktionen auf oberster Ebene. Leerzeichen gehören um Operatoren und nach Kommas, nicht direkt in Klammern: a = f(1, 2) + g(3, 4). Ein Standardwert steht ohne Leerzeichen um das =, außer der Parameter ist annotiert: times: int = 1.

Quellen

Zuletzt geprüft am 29. September 2026