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.
- Eine Funktion, die
yieldenthält, gibt einen Generator zurück und ihr Körper wird erst ausgeführt, wenn Sie nach einem Wert fragen. yieldpausiert 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 eineTypeErroraus. - 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 dieyieldin denwith-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
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.
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.
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 →DevOpsErklä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 →SoftwareentwicklungAPI-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 →TestautomatisierungSpott 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 →SoftwaretestsCode-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 & SQLDELETE 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 & SQLErklä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 →SoftwareentwicklungTypeScript-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 →SoftwareentwicklungPython *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 →SoftwareentwicklungPython-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 IntelligenzWas 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 →DevOpsDocker-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 →TestautomatisierungTDD 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 →SoftwaretestsBenutzerakzeptanztests (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 & SQLErklä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 & SQLSQL 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 →SoftwareentwicklungWas 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 →SoftwareentwicklungErklä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 →SoftwareentwicklungErklä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 IntelligenzWas 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 →DevOpsBlau-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 →TestautomatisierungFlaky-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 →SoftwaretestsLasttest 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 →SoftwaretestsTestfall 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 & SQLSQL-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 & SQLSQL 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 →SoftwareentwicklungTutorial 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 →SoftwareentwicklungUmgang 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 →SoftwareentwicklungPython-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 IntelligenzWas 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 →DevOpsLinux-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 →TestautomatisierungSelenium 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 →SoftwaretestsSchweregrad 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 & SQLTutorial 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 & SQLSQL-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 →SoftwareentwicklungGit 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 →SoftwareentwicklungPython 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 & SQLSQL 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 →