Kopiere lister

Vi vet at vi kan tilordne verdier fra én variabel til en annen.

Har vi for eksempel variabelen x, som har verdien 3, og skriver

y = x

opprettes det en ny variabel som heter y og får verdien 3.

Endrer vi senere verdien til x, påvirker ikke det verdien y har fått.

Når det gjelder lister, fungerer imidlertid tilordningsmekanismen annerledes. Skriver vi for eksempel

liste_a = [1, 2, 3, 4]
liste_b = liste_a

blir det opprettet en ny variabel som heter liste_b, men selve innholdet i liste_a blir ikke tilordnet liste_b. I stedet blir liste_b en ny variabel som refererer til det samme som liste_a.

Eksempel 1:

Vi kjører følgende Python-kode:

liste_a = [1, 2, 3, 4]
liste_b = liste_a
liste_b[1] = "hei"
print(liste_a)
print(liste_b)

I eksempel 1 oppretter vi først liste_a, så setter vi liste_b lik liste_a, deretter endrer vi et element i liste_b. Når vi så skriver ut både liste_a og liste_b, ser vi at endringen vi gjorde i liste_b også er blitt gjort i liste_a. Grunnen er at liste_a og liste_b egentlig ikke er to forskjellige lister, men bare to forskjellige navn på samme liste.

Bruker vi Python Tutor, ser vi at liste_a og liste_b refererer til samme liste:

Illustrasjon av to lister som er samme objekt

Vil vi kopiere innholdet i ei liste, kan vi enten bruke [:] som indeks for å lage ei del-liste med alle elementene, eller vi kan bruke listemetoden copy().

Eksempel 2:

Vi kjører følgende Python-kode:

liste_a = [1, 2, 3, 4]
liste_b = liste_a[:]
liste_b[1] = "hei"
print(liste_a)
print(liste_b)

og

liste_a = [1, 2, 3, 4]
liste_b = liste_a.copy()
liste_b[1] = "hei"
print(liste_a)
print(liste_b)

I begge tilfeller i eksempel 2 ser vi at endringen vi gjør i liste_b ikke påvirker liste_a. Det er fordi liste_b er blitt ei separat liste med sitt eget innhold.

Bruker vi Python Tutor, ser vi at liste_a og liste_b nå er to forskjellige lister:

Illustrasjon av to lister som er forskjellig objekt

I artikkelen om lokale og globale variabler lærer vi at variabler i funksjoner er lokale, med følgende eksempel:

Vi har en funksjon, kvadrer(), som kvadrerer verdien til parameteren x:

def kvadrer(x):
    x = x**2

I hovedprogrammet oppretter vi så en variabel, x, med verdien 4, kaller opp funksjonen med x som argument, og skriver ut verdien til x etterpå:

x = 4
kvadrer(x)
print(x)

Vi ser da at x utenfor funksjonen ikke endrer seg.

Når vi kaller opp en funksjon med ei liste som argument, er det imidlertid bare en referanse til lista som overføres til funksjonsparameteren.

Eksempel 3:

Vi har funksjonen kvadrer, som opphøyer alle elementer i ei liste i andre:

def kvadrer(liste):
    for indeks in range(len(liste)):
        liste[indeks] **= 2

I hovedprogrammet oppretter vi så lista siffer med elementene 1, 2, 3, kaller opp kvadrer() med siffer som argument, og skriver ut innholdet etterpå:

siffer = [1, 2, 3]
kvadrer(siffer)
print(siffer)

Vi ser at innholdet i siffer er blitt kvadrert, enda vi ikke har koplet siffer til noen returverdi fra funksjonen.

Bruker vi Python Tutor, ser vi at siffer i hovedprogrammet og liste i kvadrer() refererer til samme liste:

Illustrasjon av hovedprogram og funksjon som refererer til lister som er samme objekt

Oppgave 1:

I eksempel 3 kalte vi opp funksjonen kvadrer() med siffer som argument på denne måten:

kvadrer(siffer)

Vi så da et endringene som kvadrer() gjorde på sin parameter, også hadde effekt på siffer. Hvordan kan vi skrive om oppkallet av funksjonen slik at siffer ikke endres?

Se løsningsforslag

Kilder

    • Matthes A. (2019). Python Crash Course. no starch press