Werken met lijsten

Inleiding

Lijsten (list) in Python zijn een van de belangrijkste datatypes waarmee je als beginnend programmeur in aanraking zult komen. In Eerste stappen heb je er al kort kennis mee gemaakt. In dit hoofdstuk ga je dieper in op lijsten en leer je er verder mee werken.

Leerdoelen

Aan het einde van dit hoofdstuk:

  • Begrijp je wat een list is

  • Begrijp je in welke situaties je lijsten toe kunt passen

  • Begrijp je hoe je met elementen in een list kunt werken

Lijsten: een inleiding

In deze paragraaf leer je wat een list is, wat de specifieke kenmerken van lijsten zijn en hoe lijsten zich onderscheiden van andere collecties. Je leert ook in welke situaties je lijsten kunt gebruiken.

In de Eerste stappen leerde je al dat een list een reeks is, en dat de volgende methodes beschikbaar zijn:

  • Controleren of een element zich in de reeks bevindt met element in mijn_reeks (of not in).

  • Reeksen bij elkaar voegen met mijn_reeks + mijn_reeks

  • Reeksen vermenigvuldigen met mijn_reeks * 3

  • Meerdere elementen ophalen op basis van index met mijn_reeks[2:5] (slicing)

  • De lengte van de reeks bepalen met len(mijn_reeks)

  • Het grootste element uit de reeks halen met max(mijn_reeks)

  • Het kleinste element uit de reeks halen met min(mijn_reeks)

  • De index ophalen van een element uit een reeks met mijn_reeks.index(element)

  • Het aantal keer dat een element voorkomt in een reeks met mijn_reeks.count(element)

Verderop leer je hoe je deze methodes toepast.

Een list maken

Een list kun je op verschillende manieren maken. Meestal zul je de vierkante haken gebruiken ([]) of de ingebouwde functie list(). Je kunt een list leeg beginnen, maar ook direct items toevoegen:

# Lijsten maken
lege_lijst_1 = []
lege_lijst_2 = list()
lijst_met_items = [1, 2, 3, ]

Items in een list scheidt je door een komma.

Komma’s

Je zult vaak zien dat er achter het laatste item van een list ook een komma wordt geplaatst. Dit is niet verplicht. De laatst komma behoed je echter wel voor een mogelijke fout. Stel dat je een initiële versie van een list hebt, en je wilt later (handmatig) een item toevoegen:

# Initiële lijst
mijn_lijst = [
    "appel",
    "banaan",
    "peer"
]

# Aangepaste lijst, komma vergeten
mijn_lijst = [
    "appel",
    "banaan",
    "peer"
    "kiwi"
]

print(mijn_lijst)
# ['appel', 'banaan', 'peerkiwi']

Print mijn_lijst maar eens, en bekijk het resultaat. Door in de initiële list achter elk item een komma te plaatsen, voorkom je dit foutje.

Kenmerken van lijsten

De belangrijkste kenmerken van een list leerde je al in Eerste stappen:

  • Een list is een vorm van een reeks, ofwel een collectie elementen.

  • Je haalt elementen op basis van een index op uit een list.

  • De index begint bij 0, het eerste element haal je dus zo op: mijn_lijst[0].

  • Een list is muteerbaar (aanpasbaar). Je kunt elementen toevoegen, aanpassen en verwijderen.

  • De elementen in een list hoeven niet van hetzelfde type te zijn.

Opdracht 1: min, max, len

Schrijf code dat het kleinste getal, het grootste getal en de lengte van de onderstaande list print.

mijn_lijst = [1, 100, 1000, 2, ]
Klik om het antwoord te tonen
print(min(mijn_lijst))  # 1
print(max(mijn_lijst))  # 1000
print(len(mijn_lijst))  # 4

Wanneer gebruik je een lijst?

Nu je weet wat de belangrijkste kenmerken van een list zijn rijst de vraag: wanneer gebruik je een list?

Aangezien een list (meestal) meerdere elementen bevat, is het een logisch gegevenstype om te gebruiken op het moment dat je bepaalde handelingen op verschillende elementen wilt toepassen. Meestal zul je dit dan doen in een iteratie[1], bijvoorbeeld als je elke actieve gebruiker van je systeem een e-mail wilt sturen:

# Dummy code
for user in users:
    # Mail elke user indien actief
    if user.is_active:
        send_mail(user)

Vaak gaat de afweging tussen een list en tuple. Beiden zijn reeksen met elementen waar je iets mee wilt doen. Maak je een collectie op basis van gegevens, dan valt de tuple af, omdat deze niet-aanpasbaar is. Bijvoorbeeld:

# Collectie maken (list)
users = []  # Lege lijst

# Open een CSV bestand
with open("users.csv") as csvfile:
    # Gebruik de csv module om het bestand in te lezen
    csv_reader = csv.DictReader(csvfile)

    # Voor elke regel in het CSV-bestand, haal de naam op uit de kolom
    # "Name" en voeg dit toe aan de list users
    for row in csv_reader:
        users.append(row["Name"])

In bovenstaande (vereenvoudigd) voorbeeld lees je een CSV-bestand in, itereer je over elke rij en voeg je de naam die je in het CVS-bestand vindt toe aan de list users, die je op regel één hebt aangemaakt. Een resultaat ziet er als volgt uit:

print(users)
# ["Piet", "Marie", "Ali"]

Het geeft niet als je niet elke stap begrijpt, als maar duidelijk is dat je een list opbouwt. In een for-loop voeg je steeds een element toe aan een list. Met een tuple zal dit niet werken.

Je verkiest een tuple boven een list als de reeks niet zal wijzigen. Een tuple verbruikt minder geheugen en is hierdoor efficiënter. Je ziet dit vaak met korte reeksen die binnen het programma worden rondgegeven, bijvoorbeeld de coördinaten van een plaats: (long, lat).

Opdracht 2: list opbouwen

Neem de volgende list:

mijn_lijst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Schrijf een stukje code waarin je begint met een lege list en deze met een for-loop vult met het kwadraat van elk van de elementen in bovenstaande list.

Klik om het antwoord te tonen
kwadraten = []
for getal in mijn_lijst:
    kwadraten.append(getal ** 2)

print(kwadraten)

Werken met elementen in een lijst

In deze paragraaf leer je werken met de elementen in een list: ophalen, aanpassen en verwijderen.

Elementen uit een lijst ophalen

Een veelvoorkomende handeling is het ophalen van één of meerdere elementen uit een list.

Eén element ophalen

In hoofdstuk 1 in de paragraaf Collecties heb je al gezien hoe je een enkel element ophaalt uit een list, op basis van de index:

eerste_item = lijst_met_items[0]
tweede_item = lijst_met_items[1]

Met de nul-gebaseerde indexering haal je het eerste element op met [0], het tweede element met [1], etc.

Indexering kan vanaf het begin van de list, maar ook vanaf het einde. In plaats van positieve integers gebruik je dan negatieve integers. Het laatste element (dus het eerste gezien vanaf het eind) begint met index -1:

lijst_met_items = ["a", "b", "c", ]
laatste_item = lijst_met_items[-1]  # "c"

Het een-na-laatste element haal je op met [-2], het twee-na-laatste element met [-3], etc. Waar indexering vanaf het begin nul-gebaseerd is, kun je indexering vanaf het einde beschouwen als een-gebaseerd (met een min-teken ervoor).

Tabel 1. Elementen in de lijst mijn_lijst

Element

1

5

3

2

Plaats vanaf het eind

4

3

2

1

Index

-4

-3

-2

-1

Ophalen

mijn_lijst[-4]

mijn_lijst[-3]

mijn_lijst[-2]

mijn_lijst[-1]

Slicen

Soms wil je niet één, maar meerdere elementen tegelijk ophalen uit een list. Dit kan met slicen. De notatie hiervoor is [1:3].

mijn_lijst = [1, "b", "drie", 4, "V", ]
mijn_slice = mijn_lijst[1:3]  # ["b", "drie"]

Het resultaat is een nieuwe list. Let op dat de eerst index vanaf is en de tweede tot (en níet tot en met). Met [1:3] haal je dus elementen met index één en twee op, maar niet het element met index drie.

Zowel de index voor als na de dubbele punt is optioneel. Laat je de eerste index weg, dan begin je bij het begin (index 0). Laat je de laatste index weg, dan slice je tot het einde.

mijn_lijst = [1, "b", "drie", 4, "V", ]
mijn_slice = mijn_lijst[:3]  # [1, "b", "drie"]
mijn_slice = mijn_lijst[3:]  # [4, "V"]

Omdat beide indexen optioneel zijn, kun je ze ook beide weglaten:

mijn_lijst = [1, "b", "drie", 4, "V", ]
mijn_slice = mijn_lijst[:]  # [1, "b", "drie", 4, "V"]

Je maakt dan een slice vanaf het begin, tot het einde. Feitelijk maak je dan dus een kopie van de eerste list.

Een slice werkt ook met negatieve indexering.

Opdracht 3: negatieve slice

Neem onderstaande list:

mijn_lijst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Haal hier een nieuwe list uit met de waarde [4, 5, 6, 7]. Gebruik hiervoor negatieve indexering in een slice.

Klik om het antwoord te tonen
mijn_slice = mijn_lijst[-7:-3]
print(mijn_slice)

Let bij het slicen dus op dat je negatieve indexering gebruikt, maar de slice nog steeds van links naar rechts werkt. Misschien had je verwacht [-3:-7] te moeten doen, maar dit werkt niet.

Controleren of een element zich in een lijst bevindt

Soms wil je eerst weten of een element zich in een list bevindt. De meest handige manier om dit te doen is met in, of als je wilt weten of een element zich niet in een list bevindt met not in:

mijn_lijst = ["a", "a", "b", "b", "c", ]
print("a" in mijn_lijst)  # True
print("d" in mijn_lijst)  # False
print("e" not in mijn_lijst)  # True

Andere manieren om te controleren of een element zich in een list bevindt zijn .index() en .count(). Met .index() geef je een waarde op, en krijg je de index van het eerste element met die waarde terug. Met .count() geef je een waarde op en krijg je terug hoeveel elementen met die waarde zich in de list bevinden.

mijn_lijst = ["a", "a", "b", "b", "c", ]

# Met index()
print(mijn_lijst.index("a"))  # 0
print(mijn_lijst.index("d"))  # Fout

# Met count()
print(mijn_lijst.count("b"))  # 2
print(mijn_lijst.count("d"))  # 0

Hoe je de fout op regel vijf verwerkt leer je het hoofdstuk Werken met uitzonderingen. Het is afhankelijk van de context welk instrument je gebruikt. Soms is in voldoende, maar zoals uit bovenstaande voorbeelden blijkt weet je dan nog niet dat de waarde a zich vaker in de list bevindt.

Opdracht 4: index

Neem de volgende list:

mijn_lijst = ["a", "b", "c", ]

Schrijf code waarmee je de index van een element ophaalt. Zorg ervoor dat als je de index van een niet-bestaand element wilt ophalen, er geen fout ontstaat.

Klik om het antwoord te tonen
te_zoeken = "b"  # Probeer ook eens met "d"

if te_zoeken in mijn_lijst:
    print(mijn_lijst.index(te_zoeken))
else:
    print("Element niet in de lijst")

Itereren langs elementen in een lijst

Het itereren langs elementen in een list heb je al meerdere malen voorbij zien komen in voorgaande hoofdstukken. Met een for-loop ga je elk element in een list langs en kun je daar iets mee doen. Wát je ermee doet is aan jou, het blok in een for-loop kan net zo lang of kort zijn als nodig is.

Een for-statement heeft de volgende opbouw:

for <naam> in <lijst>:
    blok uitgevoerd voor elk element <naam>

Elke ronde wordt er een element uit de list gehaald en toegewezen aan de variabele <naam>. In de rest van de for-loop kun je die variabelen dan ook gebruiken zoals elke variabele.

Hoe je de variabele noemt, maakt in principe niet uit. Soms zie je dat het heel algemeen blijft (i, item, x), maar handiger is het om het iets beschrijvender te maken. Bevat je list boektitels, dan is book logisch. Bevat de list gebruikers, dan noem je het user, etc.

Een veelgehoorde uitdrukking in het programmeren is dat code vaker wordt gelezen dan geschreven. Jij en je collega’s lezen code om te begrijpen wat er gaande is, wat een functie ook alweer doet, etc.

Daarom is het belangrijk om variabelen, functies, klassen en namen in een for-loop duidelijke namen te geven. Elke naam geeft inzicht in wat er gaande is.

Dit geldt ook voor projecten waar je in je eentje aan werkt. Over zes maanden ben je blij als je oude code duidelijk is omschreven!

Soms wil je niet alleen dat het element aan de variabele wordt gekoppeld, maar wil je ook de index van de elementen bijhouden. Dit doe je met enumerate. Optioneel geef je op waar de index moet starten.

users = ["marie", "john", "ali", ]

# Index start bij 0
for index, user in enumerate(users):
    print(f"Index {index}: {user}")

# Index start bij 1
for ronde, user in enumerate(users, 1):
    print(f"Ronde {ronde}: {user}")

In plaats van één naam op te geven in de for-statement, geef je er twee op gescheiden door een komma. Verder roep je de functie enumerate aan met de list als argument (en optioneel de start van de index).

Je ziet dat het ook hier weer niet uitmaakt hoé je de variabelen noemt. In het eerste geval is het index, user en in het tweede geval ronde, user.

Elementen in een lijst sorteren en omkeren

Een list kun je zowel sorteren als omkeren.

Sorteren

Met de .sort() methode sorteer je de elementen in een list. Standaard is de sortering van laag naar hoog. Je kunt .sort(reverse=True) gebruiken om de sortering om te draaien.

mijn_lijst = ["b", "a", "d", "c", ]
mijn_lijst.sort()
print(mijn_lijst)  # ["a", "b", "c", "d"]

Dit sorteren past de bestaande list aan, er wordt dus geen nieuw object aangemaakt. Het sorteren werkt alleen als de elementen in de list met elkaar vergeleken kunnen worden.

mijn_lijst = ["a", 2, "b", 3, ]
mijn_lijst.sort()  # Fout

Voer je deze code uit, dan krijg je een foutmelding die aangeeft dat het sorteren niet lukt.

Tot slot kun je opgeven hoe je wilt sorteren, door een functie mee te geven aan .sort() die de sleutel ophaalt uit elk element en dat gebruikt om te sorteren. Je kunt bijvoorbeeld de ingebouwde functie len() gebruikte om de lengte van een str te bepalen.

print(len("test"))  # 4

# Gebruik len als sleutel om te sorteren
mijn_lijst = ["aaa", "bb", "c", ]
mijn_lijst.sort(key=len)
print(mijn_lijst)  # ["c", "bb", "aaa"]

Met sort(key=len) zorg je ervoor dat eerst len() op elk element wordt uitgevoerd, dit levert voor elk element een waarde op (3, 2 en 1 in dit voorbeeld) en deze waarden worden gebruikt om de list te sorteren.

In plaats van een list in-place te sorteren, kun je ook de ingebouwde functie sorted() gebruiken. Dit doet hetzelfde als sort(), maar levert een nieuwe list op. Het voordeel van sorted is dat het niet alleen op list werkt, maar bij alle iterables, zoals een tuple.

Omkeren

Naast een list sorteren, kun je een list ook omkeren. Dit doe je met de methode .reverse() of de ingebouwde functie reversed().

mijn_lijst = [1, 2, 3, 4, ]
mijn_lijst.reverse()
print(mijn_lijst)  # [4, 3, 2, 1]

Net als bij .sort() levert .reverse() geen nieuw object op. Met de ingebouwde functie reversed() bereik je dit wel.

Elementen aan een lijst toevoegen

Een veel voorkomende taak bij een list is het toevoegen van elementen. Hiervoor zijn drie methodes beschikbaar.

  • .append()

  • .insert()

  • .extend()

append

Met .append() voeg je een element toe aan het einde van de list. Je kunt één element tegelijk toevoegen. Bijvoorbeeld:

mijn_lijst = []
mijn_lijst.append("a")
print(mijn_lijst)  # ["a"]

Je kunt elk type element toevoegen, let hierbij wel op dat als je bijvoorbeeld een list of tuple toevoegt, het één element aan het einde van de oorspronkelijke list wordt:

mijn_lijst = ["a", ]
mijn_lijst.append([1, 2, 3])  # Voeg een lijst toe
print(mijn_lijst)  # ["a", [1, 2, 3]]

insert

Met .insert() voeg je een enkele item toe in de list. Je geeft het element dat je wilt toevoegen door, samen met de index waar het element geplaatst moet worden. De elementen erna zullen allemaal één index opschuiven.

mijn_lijst = ["a", "c", "d", ]
mijn_lijst.insert(1, "b")  # Voeg 'b' toe op index 1
print(mijn_lijst)  # ["a", "b", "c", "d"]

Net als bij .append() kun je bijvoorbeeld een list toevoegen, maar wordt dit één element in de oorspronkelijke list.

extend

Met .extend() voeg je alle elementen uit een iterable (zoals een list of een tuple) toe aan het einde van de huidige list:

mijn_lijst = ["a", "b", "c", ]
mijn_tuple = (1, 2, 3, )
mijn_lijst.extend(mijn_tuple)
print(mijn_lijst)  # ["a", "b", "c", 1, 2, 3]

Elementen uit een lijst verwijderen

Net als je op verschillende manieren elementen aan een list kunt toevoegen, zijn er ook verschillende manieren om één of meerdere elementen te verwijderen.

remove

Met de .remove() methode verwijder je een element op basis van de waarde. Het eerste element in de list met de opgegeven waarde wordt verwijderd (de rest dus niet, als er meerde elementen met die waarde zijn). Wordt de waarde niet gevonden, dan ontstaat een fout.

mijn_lijst = [1, 2, 3, 2, ]
mijn_lijst.remove(2)  # Verwijder element met waarde 2
print(mijn_lijst)  # [1, 3, 2]
mijn_lijst.remove(0)  # Fout

pop

Met de .pop() methode verwijder je een element op basis van de index. Het element wordt teruggegeven, zodat je het kunt opslaan in een variabele.

mijn_lijst = [1, 2, 3]
element = mijn_lijst.pop(1)  # pop element met index 1
print(element)  # 2
print(mijn_lijst)  # [1, 3]

Geef je geen index op, dan verwijder je het laatste element in de list.

del

Met het ingebouwde keyword del verwijder je één of meerdere elementen uit een list, op basis van een index of een slice.

mijn_lijst = [1, 2, 3, 4, 5]
del mijn_lijst[1]  # Verwijder element met index 1
print(mijn_lijst)  # [1, 3, 4, 5]
del mijn_lijst[1:3]  # Verwijder elementen met index 1 tot 3
print(mijn_lijst)  # [1, 5]
Opdracht 5: in, uit

Neem de volgende list:

mijn_lijst = ["a", "b", "c", ]

Voer de volgende acties uit:

  • Voeg elementen "d", "e" en "f" toe aan het einde van de list

  • Verwijder het element "c" en voeg het aan het einde van de list toe

  • Verwijder de elementen "d", "e" en "f"

Als alles goed is gegaan, heb je weer de oorspronkelijke list.

Klik om het antwoord te tonen
# Voeg de elementen "d", "e" en "f" toe
mijn_lijst.extend(["d", "e", "f"])
print(mijn_lijst)

# Verwijder het element "c" en plaats het terug aan het eind
c = mijn_lijst.pop(2)
mijn_lijst.append(c)
print(mijn_lijst)

# Verwijder nu de elementen "d", "e" en "f"
del mijn_lijst[2:5]
print(mijn_lijst)

1. Itereren is het één voor één doorlopen van items in een collectie (zoals een list, tuple, dictionary)