Zum Inhalt springen
Python Fortgeschritten 2 min

Verschachtelte Datenstrukturen in Python

Lerne den Umgang mit verschachtelten Listen, Dictionaries und JSON-Daten in Python. Mit praxisnahen Beispielen wie Schüler-Noten-System und Kontaktliste.

Aktualisiert:

Verschachtelte Datenstrukturen in Python

In der Praxis bestehen Daten selten aus einfachen Listen oder einzelnen Dictionaries. Meistens arbeiten wir mit verschachtelten Strukturen: Listen in Listen, Dictionaries in Listen, Listen in Dictionaries und viele Kombinationen mehr. In diesem Tutorial lernst du, wie du solche Strukturen erstellst, darauf zugreifst und sie effektiv verarbeitest.

Listen von Listen (2D-Listen / Matrizen)

Eine 2D-Liste ist eine Liste, die andere Listen als Elemente enthält. Damit lassen sich tabellarische Daten oder Matrizen darstellen.

# Eine 3x3 Matrix
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

# Zugriff: matrix[zeile][spalte]
print(matrix[0])     # [1, 2, 3] -- erste Zeile
print(matrix[0][0])  # 1 -- erstes Element der ersten Zeile
print(matrix[1][2])  # 6 -- dritte Spalte der zweiten Zeile
print(matrix[2][1])  # 8 -- zweite Spalte der dritten Zeile

# Über alle Elemente iterieren
for zeile in matrix:
    for element in zeile:
        print(element, end=" ")
    print()
# Ausgabe:
# 1 2 3
# 4 5 6
# 7 8 9

# Mit Index iterieren
for i in range(len(matrix)):
    for j in range(len(matrix[i])):
        print(f"matrix[{i}][{j}] = {matrix[i][j]}")

Matrizen erstellen und bearbeiten

# Matrix mit Nullen erstellen (RICHTIG)
zeilen = 3
spalten = 4
matrix = [[0 for _ in range(spalten)] for _ in range(zeilen)]
print(matrix)
# [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

# ACHTUNG: Diese Methode ist FALSCH!
falsch = [[0] * spalten] * zeilen  # Alle Zeilen sind das GLEICHE Objekt!
falsch[0][0] = 99
print(falsch)  # [[99, 0, 0, 0], [99, 0, 0, 0], [99, 0, 0, 0]] -- ALLE geändert!

# Diagonale setzen
for i in range(min(zeilen, spalten)):
    matrix[i][i] = 1
print(matrix)
# [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0]]

# Spalte extrahieren
def spalte_holen(matrix, spalten_index):
    return [zeile[spalten_index] for zeile in matrix]

m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(spalte_holen(m, 1))  # [2, 5, 8]

# Matrix transponieren (Zeilen und Spalten tauschen)
def transponieren(matrix):
    return [[zeile[i] for zeile in matrix] for i in range(len(matrix[0]))]

original = [[1, 2, 3], [4, 5, 6]]
transponiert = transponieren(original)
print(transponiert)  # [[1, 4], [2, 5], [3, 6]]

Stundenplan als 2D-Liste

# Stundenplan (Zeilen = Stunden, Spalten = Tage)
tage = ["Mo", "Di", "Mi", "Do", "Fr"]
stundenplan = [
    ["Mathe",   "Deutsch",  "Englisch", "Physik",  "Sport"],
    ["Deutsch", "Mathe",    "Kunst",    "Englisch","Musik"],
    ["Bio",     "Englisch", "Mathe",    "Chemie",  "Mathe"],
    ["Sport",   "Physik",   "Deutsch",  "Mathe",   "Bio"],
]

# Schöne Ausgabe
print(f"{'Std':<6}", end="")
for tag in tage:
    print(f"{tag:<12}", end="")
print()
print("-" * 66)

for stunde, faecher in enumerate(stundenplan, 1):
    print(f"{stunde}. Std ", end="")
    for fach in faecher:
        print(f"{fach:<12}", end="")
    print()

# Alle Stunden eines bestimmten Tages
mittwoch_index = tage.index("Mi")
print(f"\nMittwoch:")
for stunde, faecher in enumerate(stundenplan, 1):
    print(f"  {stunde}. Stunde: {faecher[mittwoch_index]}")

Listen von Dictionaries

Diese Struktur ist besonders häufig und entspricht dem Format, das du von JSON-APIs und Datenbanken kennst.

# Liste von Schülern
schueler = [
    {"name": "Anna", "alter": 16, "klasse": "10a", "note": 1.3},
    {"name": "Ben", "alter": 17, "klasse": "10b", "note": 2.7},
    {"name": "Clara", "alter": 16, "klasse": "10a", "note": 1.0},
    {"name": "David", "alter": 17, "klasse": "10b", "note": 2.3},
    {"name": "Eva", "alter": 16, "klasse": "10a", "note": 1.7},
]

# Auf einzelne Datensätze zugreifen
print(schueler[0]["name"])   # Anna
print(schueler[2]["note"])   # 1.0

# Alle Namen ausgeben
for s in schueler:
    print(f"{s['name']} (Klasse {s['klasse']}): Note {s['note']}")

# Filtern: Alle Schüler mit Note besser als 2.0
gute_schueler = [s for s in schueler if s["note"] < 2.0]
print(f"\nGute Schüler ({len(gute_schueler)}):")
for s in gute_schueler:
    print(f"  {s['name']}: {s['note']}")

# Sortieren nach Note
nach_note = sorted(schueler, key=lambda s: s["note"])
print("\nRangliste:")
for platz, s in enumerate(nach_note, 1):
    print(f"  {platz}. {s['name']}: {s['note']}")

# Durchschnittsnote berechnen
durchschnitt = sum(s["note"] for s in schueler) / len(schueler)
print(f"\nDurchschnittsnote: {durchschnitt:.2f}")

# Schüler nach Klasse gruppieren
from collections import defaultdict
klassen = defaultdict(list)
for s in schueler:
    klassen[s["klasse"]].append(s["name"])

print("\nKlassen:")
for klasse, namen in sorted(klassen.items()):
    print(f"  {klasse}: {', '.join(namen)}")

Dictionaries mit Listen als Werte

# Kurse und ihre Teilnehmer
kurse = {
    "Python": ["Anna", "Ben", "Clara"],
    "JavaScript": ["David", "Eva", "Anna"],
    "Datenbanken": ["Ben", "Clara", "David", "Eva"]
}

# Zugriff
print(kurse["Python"])        # ['Anna', 'Ben', 'Clara']
print(kurse["Python"][0])     # Anna
print(len(kurse["JavaScript"]))  # 3

# Teilnehmer hinzufügen
kurse["Python"].append("Frank")
print(kurse["Python"])  # ['Anna', 'Ben', 'Clara', 'Frank']

# Neuen Kurs erstellen
kurse["HTML/CSS"] = ["Gina", "Hannah"]

# Über alle Kurse iterieren
print("\nKursübersicht:")
for kurs, teilnehmer in kurse.items():
    print(f"\n  {kurs} ({len(teilnehmer)} Teilnehmer):")
    for t in teilnehmer:
        print(f"    - {t}")

# Wer besucht die meisten Kurse?
from collections import Counter
alle_teilnehmer = []
for teilnehmer in kurse.values():
    alle_teilnehmer.extend(teilnehmer)

zaehler = Counter(alle_teilnehmer)
print("\nAnzahl Kurse pro Person:")
for person, anzahl in zaehler.most_common():
    print(f"  {person}: {anzahl} Kurs(e)")

# Notenübersicht
noten = {
    "Anna": [1.3, 2.0, 1.7, 1.0],
    "Ben": [2.7, 3.0, 2.3, 2.0],
    "Clara": [1.0, 1.3, 1.0, 1.7]
}

print("\nNotendurchschnitte:")
for name, noten_liste in noten.items():
    schnitt = sum(noten_liste) / len(noten_liste)
    print(f"  {name}: {schnitt:.2f} (aus {len(noten_liste)} Noten)")

Verschachtelte Dictionaries

# Schulverwaltung
schule = {
    "name": "Python-Gymnasium",
    "adresse": {
        "strasse": "Codestraße 42",
        "plz": "10115",
        "stadt": "Berlin"
    },
    "klassen": {
        "10a": {
            "klassenlehrer": "Herr Müller",
            "schueler_anzahl": 28,
            "faecher": ["Mathe", "Deutsch", "Englisch", "Physik"]
        },
        "10b": {
            "klassenlehrer": "Frau Schmidt",
            "schueler_anzahl": 26,
            "faecher": ["Mathe", "Deutsch", "Englisch", "Chemie"]
        }
    },
    "kontakt": {
        "telefon": "030-123456",
        "email": "info@python-gymnasium.de",
        "website": "www.python-gymnasium.de"
    }
}

# Zugriff auf verschachtelte Werte
print(schule["name"])
print(schule["adresse"]["stadt"])
print(schule["klassen"]["10a"]["klassenlehrer"])
print(schule["klassen"]["10b"]["faecher"][2])

# Sicherer Zugriff mit get()
raum = schule.get("klassen", {}).get("10c", {}).get("raum", "Nicht vorhanden")
print(raum)  # Nicht vorhanden

# Verschachtelte Daten ändern
schule["klassen"]["10a"]["schueler_anzahl"] = 29
schule["kontakt"]["telefon"] = "030-654321"

Zugriff auf verschachtelte Daten

Hilfsfunktion fuer sicheren Zugriff

def sicherer_zugriff(daten, *schluessel, standard=None):
    """Greift sicher auf verschachtelte Dictionary-Werte zu."""
    aktuell = daten
    for s in schluessel:
        if isinstance(aktuell, dict):
            aktuell = aktuell.get(s, standard)
            if aktuell is standard:
                return standard
        elif isinstance(aktuell, (list, tuple)) and isinstance(s, int):
            try:
                aktuell = aktuell[s]
            except IndexError:
                return standard
        else:
            return standard
    return aktuell

# Verwendung
daten = {
    "benutzer": {
        "profil": {
            "name": "Anna",
            "hobbies": ["Lesen", "Programmieren"]
        }
    }
}

print(sicherer_zugriff(daten, "benutzer", "profil", "name"))
# Anna

print(sicherer_zugriff(daten, "benutzer", "profil", "hobbies", 0))
# Lesen

print(sicherer_zugriff(daten, "benutzer", "adresse", "stadt", standard="Unbekannt"))
# Unbekannt

Iteration ueber verschachtelte Strukturen

# Verschiedene Iterationsmuster

# 1. Verschachtelte Liste von Dicts
mitarbeiter = [
    {
        "name": "Anna",
        "abteilung": "Entwicklung",
        "projekte": ["Website", "App"]
    },
    {
        "name": "Ben",
        "abteilung": "Design",
        "projekte": ["Website", "Logo"]
    },
    {
        "name": "Clara",
        "abteilung": "Entwicklung",
        "projekte": ["App", "API", "Datenbank"]
    }
]

# Alle Projekte aller Mitarbeiter
print("Alle Projekte pro Mitarbeiter:")
for ma in mitarbeiter:
    print(f"\n  {ma['name']} ({ma['abteilung']}):")
    for projekt in ma["projekte"]:
        print(f"    - {projekt}")

# Alle einzigartigen Projekte
alle_projekte = set()
for ma in mitarbeiter:
    alle_projekte.update(ma["projekte"])
print(f"\nAlle Projekte: {alle_projekte}")

# Mitarbeiter pro Projekt
from collections import defaultdict
projekt_teams = defaultdict(list)
for ma in mitarbeiter:
    for projekt in ma["projekte"]:
        projekt_teams[projekt].append(ma["name"])

print("\nTeams pro Projekt:")
for projekt, team in projekt_teams.items():
    print(f"  {projekt}: {', '.join(team)}")


# 2. Dict von Dicts mit Listen
bibliothek = {
    "Fantasy": {
        "Herr der Ringe": {"autor": "Tolkien", "bewertungen": [5, 4, 5, 5]},
        "Harry Potter": {"autor": "Rowling", "bewertungen": [5, 5, 4, 5, 5]}
    },
    "Krimi": {
        "Sherlock Holmes": {"autor": "Doyle", "bewertungen": [4, 5, 4]},
        "Mord im Orient-Express": {"autor": "Christie", "bewertungen": [5, 4, 5, 4]}
    }
}

print("\nBibliothek:")
for genre, buecher in bibliothek.items():
    print(f"\n  Genre: {genre}")
    for titel, info in buecher.items():
        bewertungen = info["bewertungen"]
        schnitt = sum(bewertungen) / len(bewertungen)
        print(f"    '{titel}' von {info['autor']} "
              f"-- Bewertung: {schnitt:.1f}/5 ({len(bewertungen)} Bewertungen)")

JSON-Daten verarbeiten

JSON (JavaScript Object Notation) ist das Standardformat fuer den Datenaustausch im Web. Python kann JSON direkt in Dictionaries und Listen umwandeln.

import json

# JSON-String in Python-Objekt umwandeln (Deserialisierung)
json_string = '''
{
    "name": "Wetterdaten",
    "standort": "Berlin",
    "messungen": [
        {"tag": "Montag", "temperatur": 15.2, "regen": false},
        {"tag": "Dienstag", "temperatur": 18.7, "regen": false},
        {"tag": "Mittwoch", "temperatur": 12.1, "regen": true},
        {"tag": "Donnerstag", "temperatur": 14.5, "regen": false},
        {"tag": "Freitag", "temperatur": 16.8, "regen": true}
    ]
}
'''

daten = json.loads(json_string)
print(type(daten))  # <class 'dict'>

# Auf die Daten zugreifen
print(f"Standort: {daten['standort']}")
print(f"Anzahl Messungen: {len(daten['messungen'])}")

for m in daten["messungen"]:
    regen = "Regen" if m["regen"] else "Trocken"
    print(f"  {m['tag']}: {m['temperatur']}°C ({regen})")

# Durchschnittstemperatur
temps = [m["temperatur"] for m in daten["messungen"]]
print(f"\nDurchschnitt: {sum(temps) / len(temps):.1f}°C")
print(f"Maximum: {max(temps)}°C")
print(f"Minimum: {min(temps)}°C")

# Regentage
regentage = [m["tag"] for m in daten["messungen"] if m["regen"]]
print(f"Regentage: {', '.join(regentage)}")

JSON lesen und schreiben

import json

# Python-Objekt in JSON-String umwandeln (Serialisierung)
daten = {
    "schueler": [
        {"name": "Anna", "noten": [1.3, 2.0, 1.7]},
        {"name": "Ben", "noten": [2.7, 3.0, 2.3]}
    ]
}

# Schöner JSON-String (mit Einrückung)
json_text = json.dumps(daten, indent=2, ensure_ascii=False)
print(json_text)

# In Datei speichern
with open("schueler.json", "w", encoding="utf-8") as datei:
    json.dump(daten, datei, indent=2, ensure_ascii=False)

# Aus Datei laden
with open("schueler.json", "r", encoding="utf-8") as datei:
    geladene_daten = json.load(datei)

print(geladene_daten["schueler"][0]["name"])  # Anna

Praxis: Schueler-Noten-System

def noten_system():
    """Ein vollständiges Schüler-Noten-Verwaltungssystem."""

    schueler_db = {
        "Anna Müller": {
            "klasse": "10a",
            "faecher": {
                "Mathematik": [1.3, 2.0, 1.7, 1.0],
                "Deutsch": [2.0, 1.7, 2.3],
                "Englisch": [1.0, 1.3, 1.0, 1.7]
            }
        },
        "Ben Schmidt": {
            "klasse": "10a",
            "faecher": {
                "Mathematik": [2.7, 3.0, 2.3],
                "Deutsch": [1.7, 2.0, 1.3],
                "Englisch": [3.0, 2.7, 3.3]
            }
        },
        "Clara Weber": {
            "klasse": "10b",
            "faecher": {
                "Mathematik": [1.0, 1.3, 1.0],
                "Deutsch": [1.3, 1.0, 1.7],
                "Englisch": [1.7, 2.0, 1.3]
            }
        }
    }

    def zeugnis(name):
        """Erstellt ein Zeugnis für einen Schüler."""
        if name not in schueler_db:
            print(f"Schüler '{name}' nicht gefunden.")
            return

        schueler = schueler_db[name]
        print(f"\n{'='*50}")
        print(f"  ZEUGNIS - {name}")
        print(f"  Klasse: {schueler['klasse']}")
        print(f"{'='*50}")

        gesamt_noten = []
        for fach, noten in schueler["faecher"].items():
            schnitt = sum(noten) / len(noten)
            gesamt_noten.append(schnitt)
            print(f"  {fach:<15} {schnitt:.1f}  ({len(noten)} Noten)")

        gesamt = sum(gesamt_noten) / len(gesamt_noten)
        print(f"{'─'*50}")
        print(f"  {'Gesamtdurchschnitt':<15} {gesamt:.2f}")
        print(f"{'='*50}")

    def note_hinzufuegen(name, fach, note):
        """Fügt eine Note für einen Schüler hinzu."""
        if name not in schueler_db:
            print(f"Schüler '{name}' nicht gefunden.")
            return
        if fach not in schueler_db[name]["faecher"]:
            schueler_db[name]["faecher"][fach] = []
        schueler_db[name]["faecher"][fach].append(note)
        print(f"Note {note} in {fach} für {name} eingetragen.")

    def rangliste(fach):
        """Erstellt eine Rangliste für ein bestimmtes Fach."""
        ergebnisse = []
        for name, daten in schueler_db.items():
            if fach in daten["faecher"]:
                noten = daten["faecher"][fach]
                schnitt = sum(noten) / len(noten)
                ergebnisse.append((name, schnitt))

        ergebnisse.sort(key=lambda x: x[1])
        print(f"\nRangliste {fach}:")
        for platz, (name, schnitt) in enumerate(ergebnisse, 1):
            print(f"  {platz}. {name}: {schnitt:.2f}")

    # System verwenden
    print("--- Schüler-Noten-System ---")

    # Zeugnisse erstellen
    for name in schueler_db:
        zeugnis(name)

    # Neue Noten eintragen
    note_hinzufuegen("Anna Müller", "Mathematik", 1.0)
    note_hinzufuegen("Ben Schmidt", "Physik", 2.3)

    # Ranglisten
    rangliste("Mathematik")
    rangliste("Deutsch")

noten_system()

Praxis: Kontaktliste

import json

def kontaktliste():
    """Kontaktverwaltung mit verschachtelten Datenstrukturen."""

    kontakte = [
        {
            "name": "Anna Müller",
            "telefon": {"privat": "0170-1234567", "arbeit": "030-9876543"},
            "email": "anna@beispiel.de",
            "adresse": {
                "strasse": "Hauptstraße 1",
                "plz": "10115",
                "stadt": "Berlin"
            },
            "tags": ["Familie", "Arbeit"]
        },
        {
            "name": "Ben Schmidt",
            "telefon": {"privat": "0171-2345678"},
            "email": "ben@beispiel.de",
            "adresse": {
                "strasse": "Nebenstraße 42",
                "plz": "80331",
                "stadt": "München"
            },
            "tags": ["Freund", "Sport"]
        },
        {
            "name": "Clara Weber",
            "telefon": {"privat": "0172-3456789", "arbeit": "040-1111111"},
            "email": "clara@beispiel.de",
            "adresse": {
                "strasse": "Marktplatz 7",
                "plz": "20095",
                "stadt": "Hamburg"
            },
            "tags": ["Arbeit", "Schule"]
        }
    ]

    def kontakt_anzeigen(kontakt):
        """Zeigt alle Details eines Kontakts an."""
        print(f"\n  Name: {kontakt['name']}")
        print(f"  E-Mail: {kontakt['email']}")
        print(f"  Telefon:")
        for typ, nummer in kontakt["telefon"].items():
            print(f"    {typ.capitalize()}: {nummer}")
        adr = kontakt["adresse"]
        print(f"  Adresse: {adr['strasse']}, {adr['plz']} {adr['stadt']}")
        print(f"  Tags: {', '.join(kontakt['tags'])}")

    def suche_nach_tag(tag):
        """Findet alle Kontakte mit einem bestimmten Tag."""
        treffer = [k for k in kontakte if tag in k["tags"]]
        if treffer:
            print(f"\nKontakte mit Tag '{tag}':")
            for k in treffer:
                print(f"  - {k['name']}")
        else:
            print(f"Keine Kontakte mit Tag '{tag}' gefunden.")

    def suche_nach_stadt(stadt):
        """Findet alle Kontakte in einer bestimmten Stadt."""
        treffer = [k for k in kontakte if k["adresse"]["stadt"].lower() == stadt.lower()]
        if treffer:
            print(f"\nKontakte in {stadt}:")
            for k in treffer:
                print(f"  - {k['name']}: {k['telefon'].get('privat', 'Keine Nummer')}")
        else:
            print(f"Keine Kontakte in {stadt} gefunden.")

    def als_json_speichern(dateiname):
        """Speichert die Kontakte als JSON-Datei."""
        with open(dateiname, "w", encoding="utf-8") as f:
            json.dump(kontakte, f, indent=2, ensure_ascii=False)
        print(f"Kontakte in '{dateiname}' gespeichert.")

    # Kontaktliste verwenden
    print("--- Kontaktliste ---")

    # Alle Kontakte anzeigen
    for kontakt in kontakte:
        kontakt_anzeigen(kontakt)

    # Nach Tags suchen
    suche_nach_tag("Arbeit")
    suche_nach_tag("Familie")

    # Nach Stadt suchen
    suche_nach_stadt("Berlin")
    suche_nach_stadt("Hamburg")

    # Statistik
    alle_staedte = {k["adresse"]["stadt"] for k in kontakte}
    alle_tags = set()
    for k in kontakte:
        alle_tags.update(k["tags"])

    print(f"\nStatistik:")
    print(f"  Kontakte: {len(kontakte)}")
    print(f"  Städte: {', '.join(sorted(alle_staedte))}")
    print(f"  Tags: {', '.join(sorted(alle_tags))}")

kontaktliste()

Flatten von verschachtelten Listen

Manchmal muss man eine verschachtelte Liste in eine flache Liste umwandeln:

# Einfaches Flatten (eine Ebene)
verschachtelt = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]

# Methode 1: List Comprehension
flach = [element for unterliste in verschachtelt for element in unterliste]
print(flach)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

# Methode 2: sum() Trick (nur fuer Listen!)
flach = sum(verschachtelt, [])
print(flach)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

# Methode 3: itertools.chain
from itertools import chain
flach = list(chain.from_iterable(verschachtelt))
print(flach)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

# Rekursives Flatten (beliebig tiefe Verschachtelung)
def flatten(liste):
    """Flacht eine beliebig tief verschachtelte Liste ab."""
    ergebnis = []
    for element in liste:
        if isinstance(element, list):
            ergebnis.extend(flatten(element))  # Rekursion
        else:
            ergebnis.append(element)
    return ergebnis

tief = [1, [2, 3], [4, [5, 6, [7, 8]]], 9]
print(flatten(tief))  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

# Generator-Variante (speichereffizient)
def flatten_generator(liste):
    for element in liste:
        if isinstance(element, list):
            yield from flatten_generator(element)
        else:
            yield element

tief = [1, [2, [3, [4, [5]]]], 6]
print(list(flatten_generator(tief)))  # [1, 2, 3, 4, 5, 6]

Tipps fuer Lesbarkeit

Bei verschachtelten Datenstrukturen ist Lesbarkeit besonders wichtig:

# SCHLECHT: Alles in einer Zeile
daten = {"schueler": [{"name": "Anna", "noten": {"mathe": [1,2,3], "deutsch": [2,1,3]}}, {"name": "Ben", "noten": {"mathe": [3,2,2], "deutsch": [1,2,1]}}]}

# GUT: Sauber eingerückt
daten = {
    "schueler": [
        {
            "name": "Anna",
            "noten": {
                "mathe": [1, 2, 3],
                "deutsch": [2, 1, 3]
            }
        },
        {
            "name": "Ben",
            "noten": {
                "mathe": [3, 2, 2],
                "deutsch": [1, 2, 1]
            }
        }
    ]
}

# Tipp 1: Zwischenvariablen verwenden
# SCHWER LESBAR:
print(daten["schueler"][0]["noten"]["mathe"][2])

# BESSER:
erster_schueler = daten["schueler"][0]
mathe_noten = erster_schueler["noten"]["mathe"]
dritte_note = mathe_noten[2]
print(dritte_note)

# Tipp 2: Hilfsfunktionen schreiben
def get_noten(daten, schueler_index, fach):
    """Holt die Noten eines Schülers in einem Fach."""
    try:
        return daten["schueler"][schueler_index]["noten"][fach]
    except (KeyError, IndexError):
        return []

print(get_noten(daten, 0, "mathe"))   # [1, 2, 3]
print(get_noten(daten, 5, "mathe"))   # [] (Index existiert nicht)

# Tipp 3: pprint für schöne Ausgabe
from pprint import pprint

komplexe_daten = {
    "server": {
        "host": "localhost",
        "port": 8080,
        "features": ["auth", "logging", "caching"],
        "database": {
            "type": "postgresql",
            "host": "db.beispiel.de",
            "port": 5432
        }
    }
}

# Normale Ausgabe (schwer lesbar)
print(komplexe_daten)

# Schöne Ausgabe mit pprint
pprint(komplexe_daten, indent=2)

# Tipp 4: Datenklassen verwenden (ab Python 3.7)
from dataclasses import dataclass
from typing import List

@dataclass
class Schueler:
    name: str
    klasse: str
    noten: List[float]

    @property
    def durchschnitt(self):
        return sum(self.noten) / len(self.noten) if self.noten else 0

studenten = [
    Schueler("Anna", "10a", [1.3, 2.0, 1.7]),
    Schueler("Ben", "10b", [2.7, 3.0, 2.3]),
]

for s in studenten:
    print(f"{s.name}: {s.durchschnitt:.2f}")

Uebungen

Uebung 1: Klassenarbeit auswerten

Erstelle ein Programm, das eine Klassenarbeit auswertet. Die Daten sind als verschachtelte Struktur gegeben.

klassenarbeit = {
    "fach": "Mathematik",
    "datum": "2026-02-10",
    "ergebnisse": [
        {"name": "Anna", "punkte": 45, "max_punkte": 50},
        {"name": "Ben", "punkte": 32, "max_punkte": 50},
        {"name": "Clara", "punkte": 48, "max_punkte": 50},
        {"name": "David", "punkte": 28, "max_punkte": 50},
        {"name": "Eva", "punkte": 41, "max_punkte": 50},
    ]
}

# Berechne fuer jeden Schueler:
# - Prozent erreicht
# - Note (ab 90%: 1, 80%: 2, 70%: 3, 60%: 4, 50%: 5, unter 50%: 6)
# Erstelle eine Rangliste und berechne den Klassendurchschnitt.

Uebung 2: Warenkorb

Erstelle ein Warenkorbsystem mit verschachtelten Datenstrukturen.

produkte = {
    "A001": {"name": "Laptop", "preis": 999.99, "bestand": 10},
    "A002": {"name": "Maus", "preis": 29.99, "bestand": 50},
    "A003": {"name": "Tastatur", "preis": 79.99, "bestand": 30},
    "A004": {"name": "Monitor", "preis": 349.99, "bestand": 15},
}

warenkorb = []  # Liste von {"produkt_id": ..., "menge": ...}

# Implementiere Funktionen:
# - zum_warenkorb(produkt_id, menge)
# - warenkorb_anzeigen()
# - gesamtpreis()
# - warenkorb_leeren()

Uebung 3: JSON-Daten analysieren

Analysiere die folgende JSON-Struktur und beantworte die Fragen im Code.

import json

bibliothek_json = '''
{
    "bibliothek": "Stadtbibliothek Berlin",
    "buecher": [
        {"titel": "Python Grundlagen", "autor": "Max Muster", "jahr": 2023, "genre": "Sachbuch", "ausgeliehen": true},
        {"titel": "Der Hobbit", "autor": "J.R.R. Tolkien", "jahr": 1937, "genre": "Fantasy", "ausgeliehen": false},
        {"titel": "Clean Code", "autor": "Robert Martin", "jahr": 2008, "genre": "Sachbuch", "ausgeliehen": true},
        {"titel": "Harry Potter", "autor": "J.K. Rowling", "jahr": 1997, "genre": "Fantasy", "ausgeliehen": false},
        {"titel": "Algorithmen", "autor": "Thomas Cormen", "jahr": 2009, "genre": "Sachbuch", "ausgeliehen": false}
    ]
}
'''

daten = json.loads(bibliothek_json)

# 1. Wie viele Buecher gibt es insgesamt?
# 2. Welche Buecher sind ausgeliehen?
# 3. Wie viele Buecher gibt es pro Genre?
# 4. Welches ist das aelteste Buch?
# 5. Liste aller verfuegbaren (nicht ausgeliehenen) Buecher

Uebung 4: Verschachtelte Daten transformieren

Schreibe eine Funktion, die eine flache Liste von Datensaetzen in eine gruppierte, verschachtelte Struktur umwandelt.

# Eingabe: flache Liste
bestellungen = [
    {"kunde": "Anna", "produkt": "Laptop", "preis": 999},
    {"kunde": "Ben", "produkt": "Maus", "preis": 30},
    {"kunde": "Anna", "produkt": "Tastatur", "preis": 80},
    {"kunde": "Clara", "produkt": "Monitor", "preis": 350},
    {"kunde": "Ben", "produkt": "Laptop", "preis": 999},
    {"kunde": "Anna", "produkt": "Maus", "preis": 30},
]

# Erwartete Ausgabe: gruppiert nach Kunde
# {
#     "Anna": {
#         "bestellungen": [...],
#         "gesamtbetrag": 1109
#     },
#     "Ben": { ... },
#     "Clara": { ... }
# }

def gruppiere_bestellungen(bestellungen):
    # Deine Loesung hier
    pass

Pro-Tipp: Bei der Arbeit mit tief verschachtelten Daten (besonders JSON-APIs) lohnt sich ein Blick auf die Bibliothek jmespath fuer elegante Pfad-Abfragen:

# pip install jmespath
import jmespath

daten = {
    "schueler": [
        {"name": "Anna", "note": 1.3},
        {"name": "Ben", "note": 2.7},
        {"name": "Clara", "note": 1.0}
    ]
}

# Alle Namen extrahieren
namen = jmespath.search("schueler[*].name", daten)
print(namen)  # ['Anna', 'Ben', 'Clara']

# Schueler mit Note besser als 2.0
gute = jmespath.search("schueler[?note < `2.0`].name", daten)
print(gute)   # ['Anna', 'Clara']

Fuer einfachere Faelle reicht aber oft eine gut strukturierte Kombination aus Schleifen und Comprehensions voellig aus!

Zurück zum Python Kurs