Erklärung von Python-Generatoren und -Ertrag: Sparen Sie Speicher mit echten Beispielen

  1. Startseite
  2. Blog
  3. Softwareentwicklung

Softwareentwicklung

Python-Generatoren und Ertrag erklärt: Speicher sparen mit echten Beispielen

Generatoren erzeugen Werte einzeln, anstatt eine ganze Liste im Speicher zu erstellen. Beobachten Sie genau, wie yield eine Funktion anhält, sehen Sie sich den von uns gemessenen Speicherunterschied an und bauen Sie eine kleine Datenpipeline auf.

9 Min. Lesezeit
Python-Generatoren und Yield erklärt: Speicher sparen mit realen Beispielen

Das Wichtigste

  • Eine Funktion, die yield enthält, gibt einen Generator zurück und ihr Körper wird erst ausgeführt, wenn Sie nach einem Wert fragen.
  • yield pausiert die Funktion und behält ihren lokalen Status bis zur nächsten Anfrage bei.
  • Generatoren benötigen eine kleine, feste Speichermenge, unabhängig davon, wie viele Werte sie erzeugen.
  • Ein Generator kann nur einmal verbraucht werden, was die häufigste Falle ist.

Stellen Sie sich vor, Sie laden eine 10-GB-Protokolldatei in eine Liste, nur um die Fehler zu finden. Möglicherweise geht Ihrem Programm der Speicher aus, bevor es einen findet. Python-Generatoren lösen dieses Problem, indem sie Werte nach Bedarf einzeln erzeugen, sodass Sie riesige oder sogar endlose Daten fast ohne Speicher verarbeiten können.

Diese Anleitung zeigt Schritt für Schritt, was wirklich passiert, wenn ein Generator läuft. Wir haben jedes Beispiel auf Python 3.13 ausgeführt und die Ausgabe stammt von diesem Lauf. Es ist hilfreich, bereits mit Funktionen und Schleifen vertraut zu sein, die in unserem Python-Tutorial für Anfänger behandelt werden.

Was ist ein Generator?

Ein Generator ist eine besondere Art von Iterator, den Sie erstellen, indem Sie mit yield eine Funktion schreiben. Jede Funktion mit yield wird automatisch zu einer Generatorfunktion, und wenn Sie sie aufrufen, erhalten Sie ein Generatorobjekt, anstatt den Code auszuführen.

def count_up(limit):
    print("starting")
    n = 1
    while n <= limit:
        yield n
        n += 1
    print("finished")

gen = count_up(2)
print(gen)

# <generator object count_up at 0x...>

Beachten Sie, dass „starting“ nicht gedruckt wurde. Durch den Aufruf der Funktion wurde nur der Generator erstellt. Drinnen ist noch nichts gelaufen.

Wie Yield funktioniert, Schritt für Schritt

Jeder Aufruf von next() führt die Funktion aus, bis sie eine yield erreicht, gibt diesen Wert zurück und friert an Ort und Stelle ein. Der nächste Aufruf wird direkt nach dieser Zeile fortgesetzt, wobei alle lokalen Variablen intakt bleiben.

print(next(gen))
# starting
# 1

print(next(gen))
# 2

next(gen)
# finished
# StopIteration

Befolgen Sie die Ausgabe sorgfältig. „starting“ erscheint nur auf der ersten next(). Beim zweiten Schritt wird die Ausführung an der Stelle fortgesetzt, an der sie gestoppt wurde, sodass n immer noch verfügbar ist und zu 2 wird. Beim dritten Ende endet die Schleife, „fertig“ wird gedruckt, die Funktion fällt aus dem Ende und Python erhöht StopIteration, um zu signalisieren, dass nichts mehr übrig ist.

Du rufst dich selten next() an. Eine for-Schleife erledigt das für Sie und verarbeitet StopIteration leise, ebenso wie list(), sum() und ähnliche Funktionen:

print(list(count_up(3)))

# starting
# finished
# [1, 2, 3]

Rendite vs. Rendite

Aspekt Rückkehr Ertrag
Was es bewirkt Beendet die Funktion Pausiert die Funktion
Werte produziert Ein Ergebnis Eine Serie nach der anderen
Lokaler Staat Weggeworfen Zwischen Werten erhalten
Wenn der Code ausgeführt wird Sofort bei Anruf Nur wenn ein Wert angefordert wird
Speicher für viele Werte Muss sie alle halten Hält einzeln

Diese Verzögerung wird als verzögerte Auswertung bezeichnet: Werte werden nur dann berechnet, wenn sie benötigt werden. Eine einfache return in einem Generator beendet ihn einfach, was StopIteration auslöst.

Der Gedächtnisunterschied, gemessen

Wir haben eine Liste von einer Million Quadraten mit einem äquivalenten Generator verglichen und dabei sys.getsizeof verwendet:

import sys

squares_list = [n * n for n in range(1_000_000)]
squares_gen = (n * n for n in range(1_000_000))

print(sys.getsizeof(squares_list), sys.getsizeof(squares_gen))

# 8448728 200

Die eigene Struktur der Liste benötigte etwa 8,4 MB, während der Generator auf unserem System nur 200 Bytes benötigte. Die tatsächliche Lücke ist sogar noch größer, da getsizeof die ganzzahligen Objekte in der Liste nicht zählt. Auch die Größe des Generators bleibt für eine Milliarde Elemente gleich, da er nur seinen aktuellen Zustand und nicht seine Ergebnisse speichert.

Es gibt jedoch einen Kompromiss. Eine Liste kann mit len() wiederverwendet, indiziert und gemessen werden. Ein Generator bietet nichts davon. Wenn Sie wahlfreien Zugriff benötigen oder eine kleine Datenmenge mehrmals durchlaufen, ist eine Liste einfacher. Weitere Informationen zu diesen Typen finden Sie in unserem Leitfaden zu Python-Liste vs. Tupel vs. Set.

Generatorausdrücke

Für einfache Fälle benötigen Sie keine Funktion. Ein Generatorausdruck sieht aus wie ein Listenverständnis mit runden Klammern anstelle von eckigen:

squares = [n * n for n in range(5)]   # builds a list now
squares = (n * n for n in range(5))   # produces values on demand

print(sum(n * n for n in range(5)))

# 30

Wenn ein Generatorausdruck das einzige Argument einer Funktion ist, wie in sum(), können Sie die zusätzlichen Klammern weglassen. Dies ist eine gute Angewohnheit für Summen über große Datenmengen, da keine temporäre Liste erstellt wird.

Erstellen Sie eine Datenpipeline

Hier glänzen Generatoren wirklich. Kleine Generatoren können verkettet werden, sodass jedes Element nacheinander jeden Schritt durchläuft:

def read_lines(lines):
    for line in lines:
        yield line.strip()

def only_errors(lines):
    for line in lines:
        if line.startswith("ERROR"):
            yield line

def messages(lines):
    for line in lines:
        yield line.split(" ", 1)[1]

log = ["INFO started\n", "ERROR db down\n",
       "ERROR disk full\n", "INFO stopped\n"]

print(list(messages(only_errors(read_lines(log)))))

# ['db down', 'disk full']

Jeder Schritt erledigt eine kleine Aufgabe und kann einzeln getestet werden. Tauschen Sie im realen Einsatz die Beispielliste gegen eine geöffnete Datei aus, da Dateiobjekte Zeile für Zeile gelesen werden können, wie unser Leitfaden zum Python-Dateihandling zeigt. Sogar ein Multi-Gigabyte-Protokoll würde dann mit sehr wenig Speicher passieren.

Tipp: Eine Pipeline funktioniert erst, wenn sie von etwas verbraucht wird. Der Aufbau der Kette erfolgt sofort. Die Verarbeitung erfolgt nur, wenn Sie den endgültigen Generator durchlaufen oder ihn in einen Aufruf wie list() einschließen.

Unendliche Folgen

Eine Liste kann nicht unendlich sein, ein Generator jedoch schon, da er immer nur den nächsten Wert berechnet. Verwenden Sie itertools.islice, um so viele zu nehmen, wie Sie benötigen:

import itertools

def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

print(list(itertools.islice(fibonacci(), 8)))

# [0, 1, 1, 2, 3, 5, 8, 13]

Seien Sie jedoch vorsichtig: Der Aufruf von list(fibonacci()) ohne Limit würde so lange laufen, bis Ihr Speicher aufgebraucht ist. Das gleiche Muster eignet sich für ID-Generatoren, Abfrageschleifen und paginierte API-Ergebnisse, bei denen Sie die nächste Seite erst abrufen, wenn die aktuelle Seite abgelaufen ist.

Ausbeute und Chargen

yield from Überlassen Sie es einer anderen Iterable und ersparen Sie sich so eine verschachtelte Schleife:

def chain_all(*groups):
    for group in groups:
        yield from group

print(list(chain_all([1, 2], (3, 4))))

# [1, 2, 3, 4]

Ein sehr praktisches Muster ist das Aufteilen von Daten in Stapel fester Größe, um beispielsweise tausend Zeilen gleichzeitig in eine Datenbank einzufügen:

def batches(items, size):
    batch = []
    for item in items:
        batch.append(item)
        if len(batch) == size:
            yield batch
            batch = []
    if batch:
        yield batch

print(list(batches(range(7), 3)))

# [[0, 1, 2], [3, 4, 5], [6]]

Das Finale if batch stellt sicher, dass eine kleinere übrig gebliebene Gruppe nicht verloren geht. Python 3.12 und höher enthalten auch itertools.batched, das eine ähnliche Aufgabe erfüllt.

Senden, schließen und bereinigen

Auch Generatoren können Werte empfangen. send() setzt den Generator fort und der Wert wird zum Ergebnis des yield-Ausdrucks. Sie müssen next() zuerst einmal anrufen, um den ersten yield zu erreichen:

def running_total():
    total = 0
    while True:
        value = yield total
        total += value

t = running_total()
next(t)
print(t.send(10), t.send(5))

# 10 15

Die meisten Menschen brauchen dies selten. Ein häufigeres Problem ist die Bereinigung. Wenn Sie vorzeitig stoppen, läuft ein finally-Block immer noch, wenn der Generator geschlossen ist:

def tracked():
    try:
        yield 1
        yield 2
    finally:
        print("cleanup ran")

tr = tracked()
next(tr)
tr.close()

# cleanup ran

Pytest nutzt genau diese Idee: Ein Fixture mit yield führt anschließend seine Bereinigung durch, wie unser Pytest-Tutorial zeigt. Ebenso verwandelt der contextmanager-Dekorator der Standardbibliothek einen Generator in einen with-Block.

Generatoren in Klassen

Das Schreiben einer __iter__-Methode als Generator ist der einfachste Weg, Ihre eigene Klasse iterierbar zu machen. Ein Bonus ist, dass jede Schleife einen neuen Generator erhält, sodass das Objekt immer wieder wiederholt werden kann:

class Countdown:
    def __init__(self, start):
        self.start = start

    def __iter__(self):
        n = self.start
        while n > 0:
            yield n
            n -= 1

c = Countdown(3)
print(list(c), list(c))

# [3, 2, 1] [3, 2, 1]

Wann sollte ein Generator verwendet werden?

Verwenden Sie einen Generator, wenn Verwenden Sie wann eine Liste
Die Daten sind groß oder ihre Größe ist unbekannt Die Daten sind klein und passen in den Speicher
Sie verarbeiten die Artikel einmal der Reihe nach Sie machen eine Schleife mehrmals
Sie können früher aufhören Sie benötigen len(), Indizierung oder Slicing
Sie lesen einen Stream oder Dateien Sie müssen die Daten sortieren oder umkehren
Sie bauen eine Pipeline Einfachheit ist wichtiger als Erinnerung

Ein Generator ist insgesamt nicht immer schneller. Wenn Sie am Ende jeden Wert verwenden, ist die Gesamtarbeit ähnlich, und das Listenverständnis kann bei kleinen Datenmengen sogar schneller erfolgen, da weniger Overhead pro Element entsteht. Die Hauptvorteile liegen in der Speichernutzung und der schnelleren Erzielung erster Ergebnisse.

Häufige Fehler

Wiederverwendung eines erschöpften Generators

Das erwischt irgendwann fast jeden. Ein Generator merkt sich, dass er fertig ist:

g = count_up(2)
print(list(g), list(g))

# [1, 2] []

Der zweite Aufruf erhält eine leere Liste ohne Fehler. Rufen Sie die Funktion erneut auf, um einen neuen Generator zu erhalten, oder verwenden Sie den oben gezeigten Klassenansatz.

Es wird erwartet, dass der Code sofort ausgeführt wird

def noisy():
    print("body runs")
    yield 1

n = noisy()        # nothing is printed
print(next(n))     # body runs, then 1

Argumentprüfungen am Anfang eines Generators werden erst beim ersten next() ausgeführt, sodass Fehler weit entfernt von dem Aufruf auftreten können, der sie verursacht hat.

Andere Fallen

  • Aufrufen von len() oder Indizieren. Generatoren unterstützen keines von beiden und lösen eine TypeError aus.
  • Eine Datei zu früh schließen. Das Zurückgeben eines Generators aus einem with-Block kann bedeuten, dass die Datei geschlossen wird, bevor eine Zeile gelesen wird. Setzen Sie die yield in den with-Block.
  • Alles in list() einpacken. Das macht den Speichervorteil zunichte.
  • Verwenden Sie eines für kleine Daten. Eine einfache Liste ist oft klarer.

Fazit

Ein Generator ist eine Funktion, die pausieren kann. Diese eine Idee sorgt für eine geringe Speichernutzung, endlose Sequenzen und saubere Pipelines. Um es in die Praxis umzusetzen, suchen Sie in Ihrem Code eine Stelle, die eine große Liste erstellt, nur um sie einmal zu durchlaufen, und wandeln Sie diese in einen Generator um. Versuchen Sie dann, zwei kleine Generatoren in einer echten Protokolldatei miteinander zu verketten.

Häufige Fragen

Was macht yield in Python?

yield erzeugt einen Wert und hält die Funktion an, wobei die lokalen Variablen erhalten bleiben. Die Funktion wird an derselben Stelle fortgesetzt, wenn der nächste Wert angefordert wird.

Was ist der Unterschied zwischen einem Generator und einer Liste?

Eine Liste speichert alle ihre Werte auf einmal im Speicher. Ein Generator berechnet jeden Wert bei Bedarf, benötigt wenig Speicher und kann normalerweise nur einmal verwendet werden.

Was ist der Unterschied zwischen einem Iterator und einem Generator?

Jeder Generator ist ein Iterator. Ein Generator ist einfach die einfachste Möglichkeit, einen zu schreiben, da Python die Methoden __iter__ und __next__ für Sie erstellt.

Kann man einen Generator zweimal durchschleifen?

Nein. Sobald es erschöpft ist, bringt es nichts mehr, ohne einen Fehler auszulösen. Erstellen Sie einen neuen Generator, indem Sie die Funktion erneut aufrufen, oder speichern Sie die Ergebnisse in einer Liste.

Sind Generatoren schneller als Listen?

Nicht immer. Sie verbrauchen viel weniger Speicher und liefern das erste Ergebnis früher, aber das Verstehen einer Liste kann etwas schneller sein, wenn Sie kleine Datenmengen vollständig verbrauchen.

Lerne weiter

Arbeiten Sie mit Stack Quora

Benötigen Sie Hilfe beim Testen, WordPress oder SEO?

Wir helfen Teams, bessere Software zu liefern und ihre Websites zu erweitern. Sagen Sie uns, woran Sie gerade arbeiten, und wir schlagen Ihnen einen klaren nächsten Schritt vor.

Lesen Sie weiter

Weitere Anleitungen finden Sie unter Tests, KI und moderne Entwicklung

Hat Ihnen dieser Artikel gefallen? Wählen Sie ein Thema und springen Sie direkt in unsere neuesten Tutorials.

Künstliche Intelligenz

KI-Halluzinationen erklärt: Warum Sprachmodelle Dinge erfinden und wie man sie reduziert

KI-Halluzinationen erklärt: Was sie sind, warum Sprachmodelle sie produzieren, gängige Typen, wie man sie mit Erdung und Eingabeaufforderungen reduz…

Artikel lesen →
DevOps

Erklärte Umgebungsvariablen: .env-Dateien, Geheimnisse und Konfiguration richtig gemacht

Umgebungsvariablen anhand von Python-Beispielen erklärt, die wir ausgeführt haben: Sie lesen und festlegen, warum jeder Wert ein String ist, .env-Da…

Artikel lesen →
Softwareentwicklung

API-Ratenbegrenzung erklärt: Algorithmen, Header und Behandlung von 429-Fehlern

API-Ratenbegrenzung anhand einer von uns durchgeführten Simulation erklärt: Token-Bucket, festes Fenster, gleitendes Fenster, 429 Antworten, Ratenbe…

Artikel lesen →
Testautomatisierung

Spott in Python: unittest.mock, Patch und die Fehler, die Tests zum Lügen machen

Mocking in Python mit unittest.mock, getestet: Mock und return_value, side_effect, Patchen, wo ein Name verwendet wird, Spezifikation und Autospec, …

Artikel lesen →
Softwaretests

Code-Abdeckung erklärt: Leitungs- und Zweigstellenabdeckung und was 100 % wirklich bedeutet

Erklärung der Codeabdeckung anhand eines echten Coverage.py-Laufs: Zeilen-, Zweig- und Bedingungsabdeckung, Lesen eines Berichts, warum bei 100 % Ab…

Artikel lesen →
Datenbanken & SQL

DELETE vs. TRUNCATE vs. DROP in SQL: Unterschiede, Rollback und Verwendungszweck

DELETE vs. TRUNCATE vs. DROP erklärt mit getestetem SQL: was jeweils entfernt wird, Rollback, Trigger, Identitätsrücksetzung, Geschwindigkeit und wi…

Artikel lesen →
Datenbanken & SQL

Erklärte SQL-Ansichten: Erstellen, nutzen und vermeiden Sie Fallstricke mit Beispielen

SQL-Ansichten anhand der von uns ausgeführten Abfragen erklärt: Erstellen einer Ansicht, Live-Ergebnisse, Ausblenden von Spalten, Leistung, aktualis…

Artikel lesen →
Softwareentwicklung

TypeScript-Schnittstelle vs. Typ: Echte Unterschiede, getestet mit dem Compiler

TypeScript-Schnittstelle vs. Typ, überprüft mit dem echten Compiler: Was beide können, was nur einer kann, Deklarationszusammenführung, Erweiterunge…

Artikel lesen →
Softwareentwicklung

Python *args und **kwargs erklärt: Flexible Funktionen mit klaren Beispielen

Python *args und **kwargs erklärt mit Code, den wir ausgeführt haben: Packen und Entpacken, Parameterreihenfolge, Nur-Schlüsselwort- und Nur-Positio…

Artikel lesen →
Softwareentwicklung

Python-Lambda-Funktionen: Syntax, tatsächliche Verwendung und wann man sie nicht verwendet

Python-Lambda-Funktionen erklärt mit Code, den wir ausgeführt haben: Syntax, Sortierung mit Schlüssel, Karte und Filter, Abschlüsse, die Late-Bindin…

Artikel lesen →
Künstliche Intelligenz

Was sind KI-Agenten? Wie sie funktionieren, mit einer einfachen Agentenschleife, die Sie ausführen können

Was sind KI-Agenten? Eine einfache Anleitung zur Agentenschleife, zu Tools, Speicher und Leitplanken, mit einer kleinen Python-Schleife, die wir aus…

Artikel lesen →
DevOps

Überwachung vs. Beobachtbarkeit: Der wahre Unterschied, mit Protokollen, Metriken und Traces

Überwachung vs. Beobachtbarkeit erklärt: bekannte und unbekannte Fehler, Protokolle, Metriken und Spuren, eine exemplarische Vorgehensweise für Chec…

Artikel lesen →
DevOps

Docker-Volumes vs. Bind Mounts: Containerdaten auf die richtige Art und Weise beibehalten

Docker-Volumes vs. Bind-Mounts erklärt: Warum Containerdaten verschwinden, benannte Volumes, Bind-Mounts, tmpfs, Compose-Beispiele, Backups, Berecht…

Artikel lesen →
Testautomatisierung

TDD vs. BDD: Hauptunterschiede, eine Funktion, die auf beide Arten entwickelt wurde und wann sie jeweils verwendet werden sollte

TDD vs. BDD erklärt mit einer Rabattfunktion, die in beide Richtungen aufgebaut ist: Rot-Grün-Refaktor mit Code, den wir ausgeführt haben, Gegeben-W…

Artikel lesen →
Softwaretests

Benutzerakzeptanztests (UAT): Prozess, Checkliste und reale Beispiele

Benutzerakzeptanztests erklärt: Wer führt ihn durch, wie unterscheidet er sich von der Qualitätssicherung, ein siebenstufiger Prozess, eine UAT-Test…

Artikel lesen →
Datenbanken & SQL

Erklärte SQL-NULL-Werte: IS NULL, COALESCE, NULLIF und die zu vermeidenden Fallen

SQL-NULL-Werte, die mit von uns ausgeführten Abfragen erklärt wurden: dreiwertige Logik, IS NULL, COALESCE, NULLIF, wie Aggregate, Joins und Sortier…

Artikel lesen →
Datenbanken & SQL

SQL CASE WHEN-Anweisung: Syntax, reale Beispiele und häufige Fehler

SQL CASE WHEN anhand der von uns ausgeführten Abfragen erklärt: einfache und durchsuchte Formulare, Bedingungsreihenfolge, Pivots mit SUM, COUNT-Tri…

Artikel lesen →
Softwareentwicklung

Was ist JWT? JSON-Web-Tokens anhand eines funktionierenden Beispiels erklärt

Was ist JWT? JSON Web Tokens erklärt: die drei Teile, ein Token, das in dem von uns ausgeführten Code erstellt und manipuliert wurde, JWT vs. Sitzun…

Artikel lesen →
Softwareentwicklung

Erklärte JavaScript-Ereignisschleife: Aufrufstapel, Mikrotasks und Timer mit Beispielen

Die JavaScript-Ereignisschleife wurde mit dem von uns ausgeführten Code erklärt: Aufrufstapel, Aufgaben- und Mikrotask-Warteschlangen, warum setTime…

Artikel lesen →
Softwareentwicklung

Erklärung von Python-Generatoren und -Ertrag: Sparen Sie Speicher mit echten Beispielen

Python-Generatoren und Yield anhand des von uns ausgeführten Codes erklärt: wie sie angehalten und fortgesetzt werden, gemessene Speichereinsparunge…

Artikel lesen →
Künstliche Intelligenz

Was sind Einbettungen? Vektoren und Kosinusähnlichkeit einfach erklärt

Was sind Einbettungen? Ein Leitfaden in einfacher Sprache zu Vektoren, Kosinusähnlichkeit und semantischer Suche, mit einem kleinen Beispiel, das wi…

Artikel lesen →
DevOps

Blau-Grün vs. Canary-Bereitstellung: Unterschiede, Kompromisse und Auswahl

Blue-Green vs. Canary-Bereitstellung erklärt: Funktionsweise, Kosten, Risiko und Rollback, stabiles Benutzer-Bucketing, das wir getestet haben, Date…

Artikel lesen →
Testautomatisierung

Flaky-Tests: Was sie verursacht und wie man sie endgültig behebt

Flaky-Tests wurden anhand von Demos erklärt, die wir durchgeführt haben: die Hauptursachen, wie man sie bestätigt und diagnostiziert, richtige Korre…

Artikel lesen →
Softwaretests

Lasttest vs. Stresstest: Unterschiede, Metriken und k6-Beispiele

Erläuterungen zu Lasttests und Stresstests: Was die einzelnen Tests beweisen, Spike- und Soak-Tests, welche Kennzahlen wichtig sind, warum Durchschn…

Artikel lesen →
Softwaretests

Testfall vs. Testszenario: Hauptunterschiede, Beispiele und wann man sie jeweils verwendet

Testfall vs. Testszenario erklärt: klare Definitionen, eine Tabelle nebeneinander, eine Funktion zum Zurücksetzen von Passwörtern, die von Szenarios…

Artikel lesen →
Datenbanken & SQL

SQL-Abfrageoptimierung: Ausführungspläne lesen und langsame Abfragen mit Zeitvorgaben beheben

An einer Million Zeilen getestete SQL-Abfrageoptimierung: Ausführungspläne lesen, die richtigen Indizes hinzufügen, nicht sargierbare Filter korrigi…

Artikel lesen →
Datenbanken & SQL

SQL UNION vs. UNION ALL: Unterschiede, Beispiele und getestete Leistung

SQL UNION vs. UNION ALL anhand der von uns ausgeführten Abfragen erklärt: Duplikate, die Regeln, denen beide folgen, ein echter Datenfehler, gemesse…

Artikel lesen →
Softwareentwicklung

Tutorial zur JavaScript-Abruf-API: GET, POST, Fehlerbehandlung und Zeitüberschreitungen

Ein JavaScript-Abruf-API-Tutorial, das auf einem lokalen Server getestet wurde: GET und POST, warum 404 nicht ausgelöst wird, ein wiederverwendbarer…

Artikel lesen →
Softwareentwicklung

Umgang mit Python-Dateien: Lesen, Schreiben, CSV, JSON und Pathlib mit Beispielen

Die Handhabung von Python-Dateien wird anhand des von uns ausgeführten Codes erklärt: Öffnungsmodi, Lesen großer Dateien, CSV, JSON, Pathlib, Binärd…

Artikel lesen →
Softwareentwicklung

Python-Klassen und -Objekte: OOP-Tutorial mit echten Beispielen

Python-Klassen und -Objekte erklärt mit Code, den wir ausgeführt haben: __init__, Methoden, Klassen- und Instanzattribute, Vererbung, Eigenschaften,…

Artikel lesen →
Künstliche Intelligenz

Was ist ein großes Sprachmodell? Wie LLMs funktionieren, ohne großen Hype erklärt

Was ist ein großes Sprachmodell? LLMs im Klartext erklärt: Token, Einbettungen, Aufmerksamkeit, Training, Temperatur- und Kontextfenster, eine klein…

Artikel lesen →
DevOps

Linux-Befehle für Anfänger: Der grundlegende Terminal-Leitfaden mit Beispielen

Linux-Befehle für Anfänger, gruppiert nach Aufgaben: Navigation, Dateien, Anzeigen von Protokollen, Grep, Pipes, Berechtigungen, Prozesse und Archiv…

Artikel lesen →
Testautomatisierung

Selenium vs. Playwright: Hauptunterschiede, Code im Vergleich und welche Sie wählen sollten

Selenium vs. Playwright im Vergleich: Architektur, Wartezeit, Browser- und Sprachunterstützung, Debugging, der gleiche Test in beiden Tools, Migrati…

Artikel lesen →
Softwaretests

Äquivalenzpartitionierung: Testdesigntechnik anhand von Beispielen erklärt

Erklärung der Äquivalenzpartitionierung: Wie man gültige und ungültige Partitionen findet, Beispiele für Alter, Passwörter und Gutscheine, von uns d…

Artikel lesen →
Softwaretests

Schweregrad vs. Priorität beim Softwaretest: Unterschiede, Matrix und reale Beispiele

Schweregrad vs. Priorität beim Softwaretest erklärt: klare Definitionen, eine Vier-Wege-Matrix mit Beispielen, Stufenskalen, wer die einzelnen Punkt…

Artikel lesen →
Datenbanken & SQL

Tutorial zu SQL-Unterabfragen: Typen, korrelierte Unterabfragen und EXISTS mit Beispielen

Ein SQL-Unterabfrage-Tutorial mit Abfragen, die wir ausgeführt haben: Skalar-, IN-, FROM- und SELECT-Unterabfragen, korrelierte Unterabfragen, EXIST…

Artikel lesen →
Datenbanken & SQL

SQL-Transaktionen und ACID erklärt: COMMIT, ROLLBACK und Isolationsstufen

SQL-Transaktionen und ACID anhand einer von uns durchgeführten Banküberweisung erklärt: COMMIT, ROLLBACK, Sicherungspunkte, Sperren, Isolationsstufe…

Artikel lesen →
Softwareentwicklung

Git merge vs rebase: Unterschiede, Beispiele und wann man was nutzt

Git merge vs rebase erklärt mit echter Log-Ausgabe, einer Vergleichstabelle, der goldenen Regel des Rebase und einem sicheren Team-Workflow.

Artikel lesen →
Softwareentwicklung

Python List Comprehension: Syntax, Beispiele und wann man darauf verzichtet

Python List Comprehension erklärt: Syntax, Filter, if-else, verschachtelte Schleifen, gemessene Zeiten und Fälle, in denen eine normale for-Schleife…

Artikel lesen →
Datenbanken & SQL

SQL Joins erklärt mit Beispielen (Inner, Left, Right, Full)

SQL Joins Schritt für Schritt mit Beispieltabellen und Abfragen verstehen: INNER, LEFT, RIGHT, FULL, CROSS und SELF, plus typische Fehler und Perfor…

Artikel lesen →