Python-generatoren en opbrengst uitgelegd: bespaar geheugen met echte voorbeelden

  1. Home
  2. Blog
  3. Softwareontwikkeling

Softwareontwikkeling

Python-generatoren en rendement uitgelegd: Bespaar geheugen met echte voorbeelden

Generatoren produceren waarden één voor één in plaats van een hele lijst in het geheugen op te bouwen. Bekijk precies hoe de opbrengst een functie pauzeert, bekijk het geheugenverschil dat we hebben gemeten en bouw een kleine datapijplijn.

9 min leestijd
Python-generatoren en opbrengst uitgelegd: bespaar geheugen met echte voorbeelden

Belangrijkste punten

  • Een functie die yield bevat, retourneert een generator en de hoofdtekst ervan wordt pas uitgevoerd als u om een waarde vraagt.
  • yield pauzeert de functie en behoudt de lokale status tot het volgende verzoek.
  • Generatoren gebruiken een kleine, vaste hoeveelheid geheugen, ongeacht het aantal waarden dat ze produceren.
  • Een generator kan slechts één keer worden verbruikt, wat de meest voorkomende valkuil is.

Stel je voor dat je een logbestand van 10 GB in een lijst laadt, alleen maar om de fouten te vinden. Het is mogelijk dat uw programma onvoldoende geheugen heeft voordat het er een vindt. Python-generatoren lossen dit op door waarden op aanvraag één voor één te produceren, zodat je met vrijwel geen geheugen door enorme of zelfs eindeloze gegevens kunt werken.

Deze gids laat stap voor stap zien wat er werkelijk gebeurt als een generator draait. We hebben elk voorbeeld uitgevoerd op Python 3.13 en de uitvoer komt uit die run. Het helpt als je al vertrouwd bent met de functies en loops, die in onze Python-tutorial voor beginners worden besproken.

Wat is een generator?

Een generator is een speciaal soort iterator die u maakt door een functie te schrijven met behulp van yield. Elke functie met yield erin wordt automatisch een generatorfunctie, en als je deze aanroept, krijg je een generatorobject in plaats van dat je de code uitvoert.

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...>

Merk op dat “starten” niet werd afgedrukt. Door de functie aan te roepen, werd alleen de generator gemaakt. Er is nog niets binnengelopen.

Hoe rendement werkt, stap voor stap

Elke aanroep naar next() voert de functie uit totdat deze een yield bereikt, geeft die waarde terug en blijft op zijn plaats hangen. De volgende oproep wordt direct na die regel hervat, waarbij elke lokale variabele intact is.

print(next(gen))
# starting
# 1

print(next(gen))
# 2

next(gen)
# finished
# StopIteration

Volg de uitvoer zorgvuldig. “starten” verschijnt alleen op de eerste next(). Op de tweede keer gaat de uitvoering verder vanaf het punt waar deze stopte, dus n is nog steeds beschikbaar en wordt 2. Op de derde keer eindigt de lus, wordt ‘voltooid’ afgedrukt, valt de functie van het einde en verhoogt Python StopIteration om aan te geven dat er niets meer over is.

Je belt zelf zelden next(). Een for lus doet het voor je en handelt StopIteration rustig af, en dat geldt ook voor list(), sum() en soortgelijke functies:

print(list(count_up(3)))

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

rendement versus rendement

Aspect terug rendement
Wat het doet Beëindigt de functie Pauzeert de functie
Waarden geproduceerd Eén resultaat Een serie, één voor één
Lokale staat Weggegooid Behouden tussen waarden
Wanneer de code wordt uitgevoerd Meteen als er gebeld wordt Alleen als er een waarde wordt opgevraagd
Geheugen voor veel waarden Moet ze allemaal vasthouden Houdt er één tegelijk vast

Deze vertraging staat bekend als luie evaluatie: waarden worden alleen uitgewerkt als dat nodig is. Een vlakte return in een generator maakt er eenvoudigweg een einde aan, wat StopIteration activeert.

Het geheugenverschil, gemeten

We hebben een lijst van één miljoen vierkanten vergeleken met een gelijkwaardige generator, met behulp van sys.getsizeof:

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

De eigen structuur van de lijst nam ongeveer 8,4 MB in beslag, terwijl de generator op ons systeem slechts 200 bytes in beslag nam. De werkelijke kloof is zelfs nog groter, omdat getsizeof de gehele objecten in de lijst niet meetelt. De grootte van de generator blijft ook voor een miljard items hetzelfde, omdat deze alleen de huidige status opslaat en niet de resultaten.

Er is echter een wisselwerking. Met len() kan een lijst hergebruikt, geïndexeerd en gemeten worden. Een generator biedt dit allemaal niet. Als u willekeurige toegang nodig heeft, of als u meerdere keren een kleine hoeveelheid gegevens moet herhalen, is een lijst eenvoudiger. Zie onze gids voor Python-lijst versus tupel versus set voor meer informatie over deze typen.

Generator-expressies

Voor eenvoudige gevallen heb je geen functie nodig. Een generatorexpressie ziet eruit als een lijstbegrip met ronde haakjes in plaats van vierkante:

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

Wanneer een generatorexpressie het enige argument voor een functie is, zoals in sum(), kunt u de extra haakjes weglaten. Dit is een nette gewoonte voor totalen over grote gegevens, omdat er geen tijdelijke lijst wordt gemaakt.

Bouw een datapijplijn

Dit is waar generatoren echt uitblinken. Kleine generatoren kunnen aan elkaar worden gekoppeld, zodat elk item één voor één elke stap doorloopt:

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']

Elke stap doet één klein klusje en kan op zichzelf worden getest. Bij echt gebruik kunt u de voorbeeldlijst vervangen door een geopend bestand, omdat bestandsobjecten regel voor regel kunnen worden gelezen, zoals onze gids voor Python-bestandsverwerking laat zien. Zelfs een log van meerdere gigabytes zou dan met heel weinig geheugen passeren.

Tip: Een pijplijn werkt niet totdat iets deze verbruikt. Het opbouwen van de keten gebeurt in een handomdraai. De verwerking vindt alleen plaats wanneer u de laatste generator doorloopt of deze in een oproep verpakt, zoals list().

Oneindige reeksen

Een lijst kan niet oneindig zijn, maar een generator wel, omdat deze alleen de volgende waarde berekent. Gebruik itertools.islice om er zoveel te nemen als je nodig hebt:

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]

Wees echter voorzichtig: het aanroepen van list(fibonacci()) zonder limiet zou duren totdat je geheugen verdwenen is. Hetzelfde patroon is geschikt voor ID-generatoren, pollinglussen en gepagineerde API-resultaten, waarbij u de volgende pagina pas ophaalt als de huidige leeg is.

opbrengst uit en batches

yield from ga verder met een andere iterabele, waardoor je een geneste lus bespaart:

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

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

# [1, 2, 3, 4]

Een heel praktisch patroon is het opsplitsen van gegevens in batches van vaste grootte, bijvoorbeeld om duizend rijen tegelijk in een database in te voegen:

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]]

De laatste if batch zorgt ervoor dat er geen kleinere overgebleven groep verloren gaat. Python 3.12 en hoger bevatten ook itertools.batched, dat een soortgelijke taak vervult.

verzenden, sluiten en opruimen

Generatoren kunnen ook waarden ontvangen. send() hervat de generator en de waarde wordt het resultaat van de expressie yield. U moet eerst één keer next() bellen om de eerste yield te bereiken:

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

De meeste mensen hebben dit zelden nodig. Een meer algemeen probleem is opruimen. Als je eerder stopt, loopt er nog steeds een finally blok als de generator gesloten is:

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

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

# cleanup ran

Pytest gebruikt precies dit idee: een armatuur met yield voert de opschoning achteraf uit, zoals onze pytest-tutorial laat zien. Op dezelfde manier verandert de contextmanager decorateur van de standaardbibliotheek een generator in een with blok.

Generatoren in klassen

Het schrijven van een __iter__ methode als generator is de gemakkelijkste manier om je eigen klasse itereerbaar te maken. Een bonus is dat elke lus een nieuwe generator krijgt, zodat het object steeds opnieuw kan worden herhaald:

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]

Wanneer moet u een generator gebruiken?

Gebruik een generator wanneer Gebruik een lijst wanneer
De gegevens zijn groot of de omvang ervan is onbekend Gegevens zijn klein en passen in het geheugen
Je verwerkt artikelen één keer, op volgorde Je loopt meerdere keren rond
Het kan voorkomen dat u eerder stopt Je hebt len() nodig, indexeren of slicen
Je leest een stream of bestanden U moet de gegevens sorteren of omkeren
Je bouwt een pijplijn Eenvoud is belangrijker dan geheugen

Een generator is over het algemeen niet altijd sneller. Als je uiteindelijk elke waarde gebruikt, is het totale werk vergelijkbaar en kan het begrijpen van een lijst zelfs sneller gaan voor kleine gegevens, omdat er minder overhead per item is. De belangrijkste voordelen zijn het geheugengebruik en het sneller verkrijgen van de eerste resultaten.

Veel voorkomende fouten

Een uitgeputte generator hergebruiken

Dit overkomt bijna iedereen op een gegeven moment. Een generator onthoudt dat het klaar is:

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

# [1, 2] []

De tweede oproep krijgt een lege lijst zonder enige fout. Roep de functie opnieuw aan om een ​​nieuwe generator te krijgen, of gebruik de hierboven getoonde klassenbenadering.

Er wordt verwacht dat de code onmiddellijk wordt uitgevoerd

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

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

Argumentcontroles bovenaan een generator worden pas uitgevoerd bij de eerste next(), dus fouten kunnen ver verwijderd zijn van de oproep die ze heeft veroorzaakt.

Andere vallen

  • Calen len() of indexeren. Generatoren ondersteunen geen van beide en verhogen een TypeError.
  • Een bestand te vroeg sluiten. Het retourneren van een generator vanuit een with blok kan betekenen dat het bestand wordt gesloten voordat er een regel is gelezen. Plaats de yield in het with blok.
  • Alles inpakken list(). Dat gooit het geheugenvoordeel weg.
  • Gebruik er één voor kleine gegevens. Een eenvoudige lijst is vaak duidelijker.

Tot slot

Een generator is een functie die kan pauzeren. Dat ene idee zorgt voor een laag geheugengebruik, eindeloze reeksen en schone pijplijnen. Om het in de praktijk te brengen, zoek je een plek in je code waar een grote lijst wordt opgebouwd die je maar één keer kunt doorlopen, en verander je die in een generator. Probeer dan twee kleine generatoren aan elkaar te koppelen in een echt logbestand.

Veelgestelde vragen

Wat doet opbrengst in Python?

yield produceert een waarde en pauzeert de functie, waarbij de lokale variabelen behouden blijven. De functie wordt vanaf hetzelfde punt hervat wanneer de volgende waarde wordt opgevraagd.

Wat is het verschil tussen een generator en een lijst?

Een lijst slaat alle waarden tegelijk in het geheugen op. Een generator berekent elke waarde op aanvraag, gebruikt weinig geheugen en kan doorgaans maar één keer worden verbruikt.

Wat is het verschil tussen een iterator en een generator?

Elke generator is een iterator. Een generator is eenvoudigweg de gemakkelijkste manier om er een te schrijven, omdat Python de methoden __iter__ en __next__ voor u maakt.

Kun je een generator twee keer doorlussen?

Nee. Eenmaal uitgeput levert het niets meer op, zonder dat er een fout ontstaat. Maak een nieuwe generator door de functie opnieuw aan te roepen, of sla de resultaten op in een lijst.

Zijn generatoren sneller dan lijsten?

Niet altijd. Ze gebruiken veel minder geheugen en leveren eerder het eerste resultaat op, maar het begrijpen van een lijst kan iets sneller gaan als u slechts kleine hoeveelheden gegevens verbruikt.

Blijf leren

Werk met Stack Quora

Hulp nodig met testen, WordPress of SEO?

We helpen teams betere software te leveren en hun sites te laten groeien. Vertel ons waar u mee bezig bent en wij stellen een duidelijke volgende stap voor.

Blijf lezen

Meer handleidingen over testen, AI en moderne ontwikkeling

Genoten van dit artikel? Kies een onderwerp en ga direct naar onze nieuwste tutorials.

Kunstmatige intelligentie

AI-hallucinaties uitgelegd: waarom taalmodellen dingen verzinnen en hoe ze te verminderen

AI-hallucinaties uitgelegd: wat ze zijn, waarom taalmodellen ze produceren, veelvoorkomende typen, hoe je ze kunt verminderen met aarding en aanwijz…

Lees artikel →
DevOps

Omgevingsvariabelen uitgelegd: .env-bestanden, geheimen en configuratie goed gedaan

Omgevingsvariabelen uitgelegd met Python-voorbeelden die we hebben uitgevoerd: ze lezen en instellen, waarom elke waarde een string is, .env-bestand…

Lees artikel →
Softwareontwikkeling

API-snelheidsbeperking uitgelegd: algoritmen, headers en afhandeling van 429-fouten

API-snelheidsbeperking uitgelegd met een simulatie die we hebben uitgevoerd: token-bucket, vast venster, schuifvenster, 429 reacties, headers van sn…

Lees artikel →
Testautomatisering

Spotten in Python: unittest.mock, patch en de fouten die tests doen liegen

Spotten in Python met unittest.mock, getest: Mock en return_value, side_effect, patchen waar een naam wordt gebruikt, spec en autospec, spotdatums e…

Lees artikel →
Softwaretesten

Codedekking uitgelegd: lijn versus filiaaldekking en wat 100% werkelijk betekent

Codedekking uitgelegd met een echte dekking.py-run: dekking van lijnen, vertakkingen en condities, een rapport lezen, waarom 100% dekking nog steeds…

Lees artikel →
Databases & SQL

DELETE versus TRUNCATE versus DROP in SQL: verschillen, terugdraaien en wanneer elk te gebruiken

DELETE versus TRUNCATE versus DROP uitgelegd met geteste SQL: wat elk verwijdert, terugdraaien, triggers, identiteitsreset, snelheid en hoe PostgreS…

Lees artikel →
Databases & SQL

SQL-weergaven uitgelegd: creëer, gebruik en vermijd de valkuilen, met voorbeelden

SQL-weergaven uitgelegd met query's die we hebben uitgevoerd: een weergave maken, live resultaten, kolommen verbergen, prestaties, bijwerkbare en ge…

Lees artikel →
Softwareontwikkeling

TypeScript-interface versus type: echte verschillen, getest met de compiler

TypeScript-interface versus type, gecontroleerd met de echte compiler: wat beide kunnen doen, wat slechts één kan doen, samenvoegen van declaraties,…

Lees artikel →
Softwareontwikkeling

Python *args en **kwargs uitgelegd: flexibele functies met duidelijke voorbeelden

Python *args en **kwargs uitgelegd met code die we hebben uitgevoerd: in- en uitpakken, parametervolgorde, argumenten die alleen trefwoorden en posi…

Lees artikel →
Softwareontwikkeling

Python Lambda-functies: syntaxis, echt gebruik en wanneer u ze niet moet gebruiken

Python lambda-functies uitgelegd met code die we hebben uitgevoerd: syntaxis, sorteren met sleutel, kaart en filter, sluitingen, de laat-bindende va…

Lees artikel →
Kunstmatige intelligentie

Wat zijn AI-agenten? Hoe ze werken, met een eenvoudige agentloop die u kunt uitvoeren

Wat zijn AI-agenten? Een duidelijke gids voor de agentenlus, tools, geheugen en vangrails, met een kleine Python-lus die we hebben uitgevoerd, echte…

Lees artikel →
DevOps

Monitoring versus waarneembaarheid: het echte verschil, met logboeken, statistieken en sporen

Monitoring versus waarneembaarheid uitgelegd: bekende en onbekende fouten, logboeken, statistieken en sporen, een walkthrough voor afrekenincidenten…

Lees artikel →
DevOps

Docker-volumes versus bindingsmounts: bewaar containergegevens op de juiste manier

Docker-volumes versus bind-mounts uitgelegd: waarom containergegevens verdwijnen, benoemde volumes, bind-mounts, tmpfs, Compose-voorbeelden, back-up…

Lees artikel →
Testautomatisering

TDD versus BDD: belangrijkste verschillen, één functie die op beide manieren is gebouwd en wanneer deze moet worden gebruikt

TDD versus BDD uitgelegd met één kortingsfunctie die in beide richtingen is gebouwd: rood-groen-refactor met code die we hebben uitgevoerd, gegeven-…

Lees artikel →
Softwaretesten

Gebruikersacceptatietesten (UAT): proces, checklist en echte voorbeelden

Gebruikersacceptatietesten uitgelegd: wie voert het uit, hoe het verschilt van QA, een proces in zeven stappen, een UAT-testcase-sjabloon, een check…

Lees artikel →
Databases & SQL

SQL NULL-waarden uitgelegd: IS NULL, COALESCE, NULLIF en de te vermijden vallen

SQL NULL-waarden uitgelegd met query's die we hebben uitgevoerd: logica met drie waarden, IS NULL, COALESCE, NULLIF, hoe aggregaten, joins en sorter…

Lees artikel →
Databases & SQL

SQL CASE WHEN-instructie: syntaxis, echte voorbeelden en veelvoorkomende fouten

SQL CASE WHEN uitgelegd met vragen die we hebben uitgevoerd: eenvoudige en doorzochte formulieren, volgorde van de voorwaarden, draaipunten met SUM,…

Lees artikel →
Softwareontwikkeling

Wat is JWT? JSON-webtokens uitgelegd met een werkend voorbeeld

Wat is JWT? JSON Web Tokens uitgelegd: de drie delen, een token gebouwd en waarmee is geknoeid in de code die we hebben uitgevoerd, JWT versus sessi…

Lees artikel →
Softwareontwikkeling

JavaScript-gebeurtenislus uitgelegd: call-stack, microtaken en timers met voorbeelden

De JavaScript-gebeurtenislus uitgelegd met code die we hebben uitgevoerd: call-stack, taak- en microtask-wachtrijen, waarom setTimeout 0 niet onmidd…

Lees artikel →
Softwareontwikkeling

Python-generatoren en opbrengst uitgelegd: bespaar geheugen met echte voorbeelden

Python-generatoren en opbrengst uitgelegd met code die we hebben uitgevoerd: hoe ze pauzeren en hervatten, gemeten geheugenbesparingen, pijplijnen, …

Lees artikel →
Kunstmatige intelligentie

Wat zijn inbeddingen? Vectoren en cosinusovereenkomst eenvoudig uitgelegd

Wat zijn insluitingen? Een gids in duidelijke taal over vectoren, cosinusovereenkomst en semantisch zoeken, met een klein voorbeeld dat we hebben ui…

Lees artikel →
DevOps

Implementatie van blauwgroen versus kanarie: verschillen, afwegingen en hoe te kiezen

Blauw-groen versus kanarie-implementatie uitgelegd: hoe elk werkt, kosten, risico's en terugdraaien, stabiele gebruikersbucket die we hebben getest,…

Lees artikel →
Testautomatisering

Schilferige tests: wat de oorzaak ervan is en hoe u ze voorgoed kunt oplossen

Zwakke tests uitgelegd met demo's die we hebben uitgevoerd: de belangrijkste oorzaken, hoe je er een kunt bevestigen en diagnosticeren, goede oploss…

Lees artikel →
Softwaretesten

Belastingtesten versus stresstesten: verschillen, statistieken en k6-voorbeelden

Belastingtesten versus stresstesten uitgelegd: wat elk bewijst, piek- en soak-tests, de statistieken die er toe doen, waarom gemiddelden misleiden, …

Lees artikel →
Softwaretesten

Testcase versus testscenario: belangrijkste verschillen, voorbeelden en wanneer deze te gebruiken

Testcase versus testscenario uitgelegd: duidelijke definities, een tabel naast elkaar, één functie voor het opnieuw instellen van wachtwoorden, over…

Lees artikel →
Databases & SQL

Optimalisatie van SQL-query's: lees uitvoeringsplannen en repareer langzame query's, met timing

Optimalisatie van SQL-query's getest op een miljoen rijen: lees uitvoeringsplannen, voeg de juiste indexen toe, repareer niet-sargeerbare filters, g…

Lees artikel →
Databases & SQL

SQL UNION versus UNION ALL: verschillen, voorbeelden en geteste prestaties

SQL UNION versus UNION ALL uitgelegd met de query's die we hebben uitgevoerd: duplicaten, de regels volgen beide, een echte databug, gemeten prestat…

Lees artikel →
Softwareontwikkeling

JavaScript Fetch API-tutorial: GET, POST, foutafhandeling en time-outs

Een JavaScript Fetch API-tutorial getest tegen een lokale server: GET en POST, waarom 404 niet gooit, een herbruikbare helper, queryreeksen, time-ou…

Lees artikel →
Softwareontwikkeling

Python-bestandsverwerking: lezen, schrijven, CSV, JSON en pathlib met voorbeelden

Het verwerken van Python-bestanden uitgelegd met code die we hebben uitgevoerd: open modi, met het lezen van grote bestanden, CSV, JSON, pathlib, bi…

Lees artikel →
Softwareontwikkeling

Python-klassen en -objecten: OOP-zelfstudie met echte voorbeelden

Python-klassen en -objecten uitgelegd met code die we hebben uitgevoerd: __init__, methoden, klasse versus instantie-attributen, overerving, eigensc…

Lees artikel →
Kunstmatige intelligentie

Wat is een groot taalmodel? Hoe LLM's werken, uitgelegd zonder de hype

Wat is een groot taalmodel? LLM's uitgelegd in duidelijke taal: tokens, inbedding, aandacht, training, temperatuur- en contextvensters, een kleine d…

Lees artikel →
DevOps

Linux-opdrachten voor beginners: de essentiële terminalgids met voorbeelden

Linux-opdrachten voor beginners, gegroepeerd op taak: navigatie, bestanden, logboeken bekijken, grep, pipelines, machtigingen, processen en archieve…

Lees artikel →
Testautomatisering

Selenium versus toneelschrijver: belangrijkste verschillen, code vergeleken en welke te kiezen

Selenium versus Playwright vergeleken: architectuur, wachten, browser- en taalondersteuning, debuggen, dezelfde test in beide tools, migratieadvies …

Lees artikel →
Softwaretesten

Equivalentiepartitionering: testontwerptechniek uitgelegd met uitgewerkte voorbeelden

Equivalentiepartitionering uitgelegd: hoe je geldige en ongeldige partities kunt vinden, uitgewerkte voorbeelden voor leeftijden, wachtwoorden en ko…

Lees artikel →
Softwaretesten

Ernst versus prioriteit bij het testen van software: verschillen, matrix en echte voorbeelden

Ernst versus prioriteit bij het testen van software uitgelegd: duidelijke definities, een vierwegmatrix met voorbeelden, niveauschalen, wie deze bep…

Lees artikel →
Databases & SQL

Tutorial voor SQL-subquery's: typen, gecorreleerde subquery's en BESTAAN met voorbeelden

Een SQL-subquery-tutorial met query's die we hebben uitgevoerd: scalaire, IN-, FROM- en SELECT-subquery's, gecorreleerde subquery's, EXISTS, de NOT …

Lees artikel →
Databases & SQL

SQL-transacties en ACID uitgelegd: COMMIT-, ROLLBACK- en isolatieniveaus

SQL-transacties en ACID uitgelegd met een bankoverschrijving die we hebben uitgevoerd: COMMIT, ROLLBACK, savepoints, locks, isolatieniveaus, dirty r…

Lees artikel →
Softwareontwikkeling

Git merge vs rebase: verschillen, voorbeelden en wanneer je wat gebruikt

Git merge vs rebase uitgelegd met echte logoutput, een vergelijkingstabel, de gouden regel van rebase en een veilige teamwerkwijze.

Lees artikel →
Softwareontwikkeling

Python list comprehension: syntaxis, voorbeelden en wanneer je het vermijdt

Python list comprehension uitgelegd: syntaxis, filteren, if-else, geneste lussen, gemeten tijden en wanneer een gewone for-lus beter is.

Lees artikel →
Databases & SQL

SQL JOIN uitgelegd met voorbeelden (Inner, Left, Right, Full)

Begrijp SQL joins stap voor stap met voorbeeldtabellen en queries: INNER, LEFT, RIGHT, FULL, CROSS en SELF, plus veelgemaakte fouten en prestatietips.

Lees artikel →