← Python/Verzamelen en veranderen
Les 2 van 8
MODULE 04 · 02◷ 26 min

Kies tussen een alias en een kopie

Na deze les kun je
  • Slices met grenzen en stappen gebruiken
  • Een nieuwe lijst maken zonder de invoer te wijzigen
  • Een oppervlakkige kopie herkennen

Je wilt een wandelroute aanpassen zonder het oorspronkelijke plan kwijt te raken. Soms heb je alleen het middendeel van de route nodig, soms een eigen versie die je kunt uitbreiden. Daarvoor moet je onderscheid maken tussen een tweede naam voor dezelfde lijst en een nieuwe lijst.

Een deel kiezen met een slice

Een slice kiest meerdere elementen uit een reeks. Bij stops[1:3] telt de beginpositie één mee en de eindpositie drie niet. Dat sluit aan bij de eindgrens die je al van range kent.

Laat je het begin weg, dan begint de slice bij het begin van de lijst. Laat je het einde weg, dan gaat zij door tot het einde. Met items[1:-1] kies je daarom alles tussen het eerste en laatste element.

Een derde onderdeel bepaalt de stapgrootte. stops[::2] kiest posities nul, twee, vier en verder. De elementen blijven in die gekozen volgorde staan.

Een slice van een lijst levert een nieuwe lijst op. Grenzen buiten de beschikbare posities worden ingekort; een leeg gekozen deel geeft []. Daardoor werkt de slice voor het middendeel ook bij nul, één of twee elementen: er blijft dan niets over.

Twee namen of twee lijsten?

Een alias is een andere naam die naar hetzelfde object verwijst. Met alias = stops maak je dus geen tweede route. Met copy = stops[:] maak je wel een nieuwe buitenste lijst, met alle huidige elementen.

Druk op Voorbeeld uitvoeren. Kijk eerst naar de twee slices en daarna naar de routes: alleen de kopie krijgt de extra bestemming.

Een route kiezen en een eigen versie uitbreiden
stops = ["brug", "bos", "meer", "dorp"]
alias = stops
copy = stops[:]
copy.append("duin")
print(stops[1:3])
print(stops[::2])
print(alias is stops)
print(copy is stops)
print(stops)
print(copy)
Verwachte uitvoer
['bos', 'meer']
['brug', 'meer']
True
False
['brug', 'bos', 'meer', 'dorp']
['brug', 'bos', 'meer', 'dorp', 'duin']

De operator is vergelijkt objectidentiteit: gaat het om precies hetzelfde object? De operator == vergelijkt daarentegen inhoud. Twee aparte lijsten kunnen dus gelijk van inhoud zijn en toch niet hetzelfde object zijn.

stops ──┐
        ├──► lijst A: oorspronkelijke route
alias ──┘
copy ──────► lijst B: route met extra stop

Het schema laat namen en lijsten apart zien. Een verandering aan lijst A is via beide bovenste namen zichtbaar. Een verandering aan de buitenste lijst B verandert de buitenste lijst A niet.

Veelgemaakte fout: een kopie is niet altijd helemaal los

Een lijst kan zelf weer lijsten bevatten. Denk aan een buitenste lijst met twee vakjes, waarbij ieder vakje een lijst spullen bevat. Een slice maakt in dat geval een oppervlakkige kopie: alleen de buitenste lijst is nieuw.

Deze zelfstandige foutvariant gaat uit van de verkeerde verwachting dat daarmee ook ieder binnenste vakje is gekopieerd. Voorspel of de gum straks ook in de oorspronkelijke spullenlijst verschijnt.

Een nieuwe buitenkant deelt nog dezelfde vakjes
rows = [["pen"], ["boek"]]
copied = rows[:]
copied[0].append("gum")
print(rows)
print(copied)
print(copied is rows)
print(copied[0] is rows[0])
Verwachte uitvoer
[['pen', 'gum'], ['boek']]
[['pen', 'gum'], ['boek']]
False
True

Beide afgedrukte lijsten bevatten de gum. De buitenste lijsten zijn verschillend, maar hun eerste element verwijst nog naar dezelfde binnenste lijst. Het toevoegen verandert juist die gedeelde binnenste lijst.

rows   ──► buitenste lijst A ──┐
                              ├──► hetzelfde eerste vakje
copied ──► buitenste lijst B ──┘

Een oppervlakkige kopie kan precies de bedoeling zijn. Zij geeft je een onafhankelijke buitenste volgorde terwijl de elementen gedeeld blijven. Wil je ook binnenste lijsten veranderen zonder terugwerking, dan moet je die eveneens kopiëren; dat werk je later in deze module uit.

Kies het gevraagde kopieerniveau

De opdrachten oefenen eerst slices en daarna kopiecontracten. Bij een kopie uitbreiden moet de oorspronkelijke buitenste lijst gelijk blijven. Bij de opdracht shallow moeten de binnenste rijen juist dezelfde objecten blijven: maak daar geen volledig losse rijen van.

De tests controleren zowel inhoud als objectidentiteit. Alleen een nieuwe naam kiezen bewijst geen kopie, en alleen een ander object maken bewijst niet dat de juiste elementen zijn overgenomen.

AAN DE SLAG 0/4
1

Snijd de uiteinden weg

Laat middle een nieuwe lijst zonder eerste en laatste element teruggeven.

2

Sla telkens één positie over

Laat every_other posities nul, twee, vier en verder teruggeven.

3

Breid alleen de kopie uit

Laat copy_add een andere lijst teruggeven en de invoerlijst behouden.

4

Kopieer alleen de buitenkant

Laat shallow een nieuwe buitenste lijst met gedeelde rijen teruggeven.

Wat je meeneemt

  • Een slice heeft een inbegrepen begin, uitgesloten einde en optionele stap.
  • Een alias deelt hetzelfde object; een lijstslice maakt een nieuwe buitenste lijst.
  • Een oppervlakkige kopie blijft haar binnenste objecten delen.

Hierna pak je reeksen uit in namen en vang je meerdere middelste elementen tegelijk op.

main.py
UitvoerPython
›
›_

Hier komt je resultaat.

Voer je code uit en ontdek
wat je hebt gemaakt.

0/4 stappen
EVEN MEEKIJKEN

Bekijk hoe het kan.

Je mag de oplossing bekijken. Deze poging telt dan niet mee als afgeronde les. Met Reset kun je daarna opnieuw zelf oefenen.