IV OSA sisukord |
4.3 JÄRJENDI MUTEERIMINE
Pythonis on järjendid muteeritavad, mis tähendab, et järjend võib programmi töö jooksul sisaldada erinevaid väärtusi. Näiteks
järjend = [1, 2, 6, -7] print(id(järjend)) järjend[1] = 4 print(id(järjend)) järjend.append(45) print(id(järjend)) järjend += [9] print(id(järjend)) järjend = järjend + [8] print(id(järjend))
Väljastatakse arvud
20139104 20139104 20139104 20139104 9977904
Näeme, et kuni viimase muutuseni on tegemist sama järjendiobjekti muutmisega, viimane aga tekitab uue.
Mis juhtub, kui enne muteerimist on ka teine muutuja seotud?
Näeme, et tõesti on tegemist täpselt sama objektiga. Vahel on aga vaja, et koopiad oleksid sõltumatud.
Sõltumatu koopia
Kui tahame sõltumatut koopiat, siis saame kasutada viilutamist
c = a[:]
või funktsiooni copy
d = a.copy()
See sõltumatus on siiski vaid välimisel tasemel ja toimib kenasti, kui järjend koosneb mittemuteeritavatest suurustest. Kui aga järjend koosneb muteeritavatest elementidest, näiteks järjenditest, siis sügavamal tasemel jääb sõltuvus alles. See tuleb sellest, et viidad välimistele elementidele on samad.
tabel = [[1, 2, 3], [4, 5, 6]] tabel2 = tabel.copy() # või tabel2 = tabel[:] print(id(tabel[0])) print(id(tabel2[0]))
Väljastatakse
18374408 18374408
Kui nüüd muudame näiteks ühel kahemõõtmelisel järjendil ülal vasakul asetsevat elementi, siis muutub see ka teisel.
tabel = [[1, 2, 3], [4, 5, 6]] tabel2 = tabel.copy() # või tabel2 = tabel[:] # print(id(tabel[0])) # print(id(tabel2[0])) tabel2[0][0] = 12 print(tabel) print(tabel2)
Väljastatakse
[[12, 2, 3], [4, 5, 6]] [[12, 2, 3], [4, 5, 6]]
Samas välimisel tasemel on sõltumatus ja nii saame elementjärjendeid eemaldada, uusi elementjärjendeid juurde panna. Saame ka elementjärjendeid uutega asendada.
tabel = [[1, 2, 3], [4, 5, 6]] tabel2 = tabel.copy() # või tabel2 = tabel[:] tabel[1] = [23, 45, 67] print(id(tabel[1])) print(id(tabel2[1])) print(tabel) print(tabel2)
Väljastatakse
11943984 12598368 [[1, 2, 3], [23, 45, 67]] [[1, 2, 3], [4, 5, 6]]
Kuna nüüd on kummaski järjendis indeksiga 1 elementjärjent erinev (erineva viidaga), siis saame ka selles elementjärjendis ka üksikuid elemente sõltumatult muuta.
tabel = [[1, 2, 3], [4, 5, 6]] tabel2 = tabel.copy() # või tabel2 = tabel[:] tabel[1] = [23, 45, 67] tabel[1][1] = -4 print(tabel) print(tabel2)
Kui tahta täielikult sõltumatut koopiat, siis saab kasutada funktsiooni deep.copy
moodulist copy
.
from copy import deepcopy tabel3 = [[1, 2, 3], [4, 5, 6]] tabel4 = deepcopy(tabel3) tabel3[0].append(7) print(tabel3) print(tabel4)
Järjendite "korrutamine"
Pythonis on mitmeid võimalusi, mida teistes programmeerimiskeeltes ei pruugi olla. Näiteks tehtemärk *
toimib ka sõnede, järjendite ja ennikute korral.
print([1, 3, 4] * 3) print("Elagu! " * 4) print((1, 4, 6) * 2)
Kordaja võib olla ka ees, nt 4 * "Elagu"
.
Proovime nüüd *-märgi abil saada 3*4-maatriksi, mis sisaldab ainult nulle. Kuna [0] * 4
annab meile järjendi, milles on 4 nulli, siis [[0] * 4] * 3
toimel soovitu saamegi.
maatriks = [[0] * 4] * 3 print(maatriks)
Väljastatakse maatriks
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
Selline maatriks võib olla heaks aluseks mingite andmete jaoks, mida siis järjest õigetele kohtadele pannakse.
Proovime näiteks kohale (0, 0)
panna arvu 1
.
maatriks = [[0] * 4] * 3 maatriks[0][0] = 1 print(maatriks)
Väljastatakse maatriks
[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]
Näeme, et muutus toimus kõikides ridades. Seda sellepärast, et *-märgi toimel kopeeritakse vastav arv korda viitasid. Kuna need viitavad samale järjendile, siis muidugi muutuvad kõik korraga.
Kui tahta ikkagi sõltumatuid ridu saada, siis võime kirjutada järgmise funktsiooni.
def nullmaatriks(ridu, veerge): maatriks = [] for i in range(ridu): maatriks.append([0] * veerge) return maatriks maatr = nullmaatriks(3, 4) maatr[0][0] = 1 print(maatr)
IV OSA sisukord |