Ennik, sõnastik ja hulk
Ennik
Pythonis on olemas andmestruktuur, mille nimi on ennik (ingl tuple). Naljakas eestikeelne nimi on tuletatud sellest, et kolme elemendiga kogumit nimetatakse kolmikuks, nelja elemendiga nelikuks, viiega viisikuks jne. Kui sellises struktuuris on suvaline arv n elementi, siis võiks saadut nimetada nimega n-ik ehk eestipärasemalt ennik.
Enniku tähistamiseks kasutatakse ümarsulgusid ( ja ). Näiteks kolmeelemendilise enniku ehk kolmiku saame tekitada nii:
kolmik = (1, 4, 6)
Üheelemendilise enniku (üksiku) tekitamine on pisut ebaintuitiivsem:
yksik = (1,)
Koma ainukese elemendi järel ütleb Pythonile, et tegemist on ennikuga, mitte aritmeetilise avaldisega, kus ümarsulud omavad teist tähendust.
Ennikute omadusi
Paljud enniku omadused on järjendi omadustega üsna sarnased:
- Ennikus on elementide järjestus oluline: (1, 2) ei ole võrdne ennikuga (2, 1).
- Enniku elementide poole saab pöörduda indeksite abil: kui enn on ennik, siis
enn[2]
on selle enniku kolmas element. - Enniku pikkuse saame teada funktsiooni len abil.
- Mingi elemendi ennikusse kuulumist saame kontrollida võtmesõna
in
abil:3 in enn
väärtuseks on kas True või False. - Funktsioonide
min
jamax
abil saame leida ennikust vastavalt minimaalse või maksimaalse elemendi (eeldusel, et elemendid on mingil moel järjestatavad, nt arvud). - Ennikut saab viilutada: enn[1:5] annab alamenniku, milles on enn elemendid indeksitega 1, 2, 3 ja 4.
Siiski pole järjend ja ennik funktsionaalsuse mõttes võrdsed. Enniku kõige olulisem erinevus peitub selles, et see ei ole muudetav (täpsemalt muteeritav, ingl mutable). Ennikusse ei ole pärast selle tekitamist võimalik elemente lisada, neid eemaldada ega muuta, seega pole ennikul näiteks järjendite tuntud käske append
, remove
, pop
, insert
, reverse
ega extend
. Sellest tuleneb, et ennik on alati fikseeritud pikkusega.
Ennikute kasutusalad
Ennikuid kasutatakse sageli just siis, kui struktuuri pole vaja programmi käivitamise ajal muuta. Näiteks kui programmis on vaja tähistada objekte, millel on mitu omadust, kuid mida pole vaja programmi töötamise ajal muuta, siis on mõistlik nende esitamiseks kasutada ennikuid.
Samuti kasutatakse ennikuid siis, kui funktsioonist on vaja tagastada mitu väärtust. Näiteks see funktsioon leiab kahest järjendist elemendid, mille korrutis on suurim, ja tagastab need elemendid paarina:
def suurim_korrutis(lst1, lst2): suurimad = (0, 0) for el1 in lst1: for el2 in lst2: if el1 * el2 > suurimad[0] * suurimad[1]: suurimad = (el1, el2) return suurimad
Mitme väärtuse tagastamisest
Kui ühe funktsiooni asemel, mis tagastab enniku tulemustest, on võimalik teha mitu funktsiooni, millest igaüks leiab ühe üksiku (väiksema) osa tulemustest, siis on tihti parem stiil valida mitme funktsiooniga variant. Mida väiksemad ülesanded saate eri funktsioonide vahel ära jaotada, seda lihtsam on tavaliselt koodist aru saada, sealt vigu otsida ja seda hallata.
Enesekontroll
Sõnastik
Oleme tuttavad järjenditega, mille puhul igal elemendil on indeks. Nii on näiteks järjendi a = [2, 4, 7]
puhul elemendi 2 indeks 0, elemendi 4 indeks on 1 ja elemendi 7 indeks on 2. Elemendi väärtuse saab kätte indeksi järgi: a[0], a[1] ja a[2].
Teatud olukordades oleks parem, et elemendi asukohta struktuuris ei määraks mitte järjekorranumber, vaid mingi muu väärtus. Näiteks võiksime tekitada struktuuri, kus "elementideks" (väärtusteks) on inimeste vanused ja "indeksiteks" (võtmeteks) nende inimeste nimed. Sel juhul saaksime näiteks vanused["Kersti"] väärtuseks 46 ja vanused["Jüri"] väärtuseks 38. Selline andmestruktuur on Pythonis täiesti olemas ja selle nimi on sõnastik.
Sõnastik (ingl dictionary) on dünaamilise (muutuva) pikkusega andmestruktuur, mille elemendid on erilised paarid. Nende paaride esimest liiget nimetatakse võtmeks ja teist liiget väärtuseks. Koodis esitatakse sõnastik loogeliste sulgude { ja } vahel nii, et võti-väärtus paarid (kirjed) on komadega eraldatud. Paaride sees on võti ja väärtus eraldatud kooloniga.
>>> vanused = {"Kersti": 46, "Jüri": 38, "Jevgeni": 30, "Mart": 67} >>> vanused["Kersti"] 46 >>> vanused["Jüri"] 38
Võtmed ja väärtused võivad olla erinevat tüüpi. Meie näites olid võtmed sõned ja väärtused täisarvud. Sõnastiku väärtused saavad olla mistahes tüüpi, kuid võtmed peavad tehnilistel põhjustel olema mittemuteeritavat tüüpi. See tähendab, et võtmeteks sobivad näiteks arvud, sõned ja ennikud, aga ei sobi järjendid, hulgad ega teised sõnastikud. Hulkadest räägime allpool.
Sõnastikule andmete lisamine
Kui tahame sõnastikku andmeid lisada, siis saame seda teha lihtsa omistamisega:
>>> vanused["Margus"] = 33 >>> vanused {'Jüri': 38, 'Mart': 67, 'Jevgeni': 30, 'Kersti': 46, 'Margus': 33}
Sõnastikus ei saa olla korduvaid võtmeid, korduvaid väärtusi tohib olla. Kui püüda lisada uut väärtust võtmega, mis on juba sõnastikus olemas, siis eelnev väärtus kirjutatakse üle:
>>> vanused["Jevgeni"] 30 >>> vanused["Jevgeni"] = 31 >>> vanused["Jevgeni"] 31
Sõnastikku kasutataksegi niimoodi, et otsitakse võtme järgi väärtust. Vastupidi väärtuse järgi võtit kätte saada pole sõnastikust otseselt võimalik.
Sõnastiku läbimine
Sõnastikus on võti-väärtus paarid (kirjed) järjestamata. Seega ei saa nendele paaridele kuidagi indeksite kaudu ligi.
Sõnastiku läbimine for-tsükliga
Tihti kasutatakse for-tsüklit sõnastiku peal nii, et igal tsükli sammul saab tsüklimuutuja väärtuseks järjekordse võtme sõnastikust:
vanused = {"Kersti": 46, "Jüri": 38, "Jevgeni": 30, "Mart": 67} for voti in vanused: print(voti)
Selle variandiga saame väärtusele ligi tavapäraselt: vanused[voti]. See on täpselt analoogiline tsüklitele, mis töötasid järjendite indeksite peal.
Sõnastiku suurus
Sõnastiku kirjete arvu saab sarnaselt eelnevatele struktuuridele kätte len funktsiooni abil. Võtme sõnastikku kuuluvust saab kontrollida in operaatoriga:
vanused = {"Kersti": 46, "Jüri": 38, "Jevgeni": 30, "Mart": 67} kolmikud = ("Sofia", "Maria", "Kersti") for nimi in kolmikud: if nimi not in vanused: vanused[nimi] = 13 print(vanused)
See programm lisas sõnastikku uusi kirjeid ainult siis, kui need olemasolevat väärtust üle ei kirjuta.
Kirjete kustutamine sõnastikust
Sõnastikust saab kirjeid kustutada del operaatori abil:
>>> vanused = {"Kersti": 46, "Jüri": 38, "Jevgeni": 30, "Mart": 67} >>> del vanused["Jüri"] >>> vanused {'Mart': 67, 'Jevgeni': 30, 'Kersti': 46}
Sõnastik paaride hulgana
Sõnastike kirjetest saab for-tsükliga üle käia niimoodi:
vanused = {"Kersti": 46, "Jüri": 38, "Jevgeni": 30, "Mart": 67} for voti, vaartus in vanused.items(): print(voti, vaartus)
Siin vanused.items()
tagastab hulga tüüpi objekti, mis koosneb paaridest (ennikutest), kus esimesel kohal on võti ja teisel sellele vastav väärtus. Tsükli sama sammu ajal saame seega kasutada nii võtit kui ka vastavat väärtust.
Sõnastiku video
https://panopto.ut.ee/Panopto/Pages/Viewer.aspx?id=fc9d686b-a22f-45a3-b9b4-ac6300e9bde4
Enesekontroll
Hulk
Veel üks Pythoni andmestruktuur, kuhu saab mitmeid elemente paigutada, on hulk (ingl set). Hulga tähistamiseks kasutatakse loogelisi sulgusid { ja }.
Teise andmestruktuuri (nt järjendi või enniku) põhjal saab hulga teha funktsiooniga set
.
h1 = {8, 2, 3, 6, 7} h2 = set([6, 4, 5]) h3 = set('Tere hommikust')
Tühja hulga loomiseks tuleb kasutada set()
, sest tühjad loogelised sulud {} tähistavad hoopis tühja sõnastikku.
Hulk ei ole järjestatud
Nagu matemaatilises hulgaski, pole Pythoni hulgas elementide järjekord oluline. Nii võib ka Python hulga elemendid teises järjekorras esitada, kui need sisestatud on.
>>> {8, 6, 4} {8, 4, 6}
See tähendab ka muuhulgas, et kaks hulka on võrdsed siis, kui nad sisaldavad samu elemente. Need ei pea olema samas järjekorras (tegelikult polegi hulga elementidel järjekorda).
>>> {42, 11} == {11, 42} True
Kuna elementide järjekord pole määratud, siis ei saa ka üksikut elementi indeksi abil kätte. Küll aga saame for-tsükli abil hulga kõigi elementidega midagi ette võtta, hoolimata sellest, “mitmendat” elementi hetkel käsitleme:
for el in h3: print(el)
Hulgas ei ole korduvaid elemente
Teine oluline hulga tunnus pärineb samuti matemaatilistelt hulkadelt: hulgas ei ole korduvaid elemente. Kui püüame elemente hulga sees korrata, siis arvestatakse neid ikkagi ühekordselt.
>>> {4, 6, 7, 4} {4, 6, 7}
Hulgad on muudetavad
Hulgad on muteeritavad: neid saab muuta elemente lisades ja eemaldades. Kui järjendi puhul oli elemendi juurde lisamiseks käsk append
, mis tähendab lõppu lisamist, siis hulgal pole “lõppu” olemas ning lisamise käsu nimeks on add
. See lisatakse sarnaselt append
-ile hulga lõppu punktiga:
>>> h = {42, 11} >>> h.add(10) >>> h {10, 42, 11}
Veel mõned hulkade peal töötavad käsud on toodud järgmises loetelus:
h.remove(el)
- eemaldab elemendi el hulgast hh.update(h1)
- täiendab hulka h teise hulga h1 elementidegah.pop()
- eemaldab ja tagastab hulgast h (juhusliku) elemendih.clear()
- tühjendab hulga hh.copy()
- tagastab hulga h koopia
Näiteks vaatame, kuidas remove
elemendi eemaldab:
>>> h = {1, 5, 7, 3} >>> h.remove(5) >>> h {1, 3, 7}
Proovi käske ka ise!
Hulga suurus
Hulga suuruse saab leida sarnaselt järjendite ja ennikutega funktsiooniga len
. Samuti saab hulgas sisalduvust kontrollida analoogselt:
>>> h = {42, 11} >>> len(h) 2 >>> 42 in h True
Veel operatsioone hulkadega
Paljud funktsioonid nagu min
ja max
töötavad hulkadega samamoodi nagu järjendite või ennikutega.
Hulkadega saab ka selliseid operatsioone teha, mida järjendite või ennikutega ei saa. Tähtsaimad neist on toodud järgnevas loetelus. Kõik need operatsioonid on binaarsed (kahekohalised) ja vastava operatsiooni märk tuleb panna kahe hulga vahele.
&
- ühisosa ehk hulk elementidest, mida sisaldavad mõlemad hulgad|
- ühend ehk hulk elementidest, mida sisaldavad üks või teine või mõlemad hulgad-
- vahe ehk hulk elementidest, mida sisaldab esimene, aga ei sisalda teine hulk^
- sümmeetriline vahe ehk hulk elementidest, mida sisaldavad üks või teine hulk, aga mitte mõlemad<
- range alamhulk ehk kas esimene hulk on saadud teisest elemente eemaldades>
- range ülemhulk ehk kas teine hulk on saadud esimesest elemente eemaldades<=
- mitterange alamhulk ehk kas esimene hulk on saadud teisest elemente eemaldades või sellega võrdne>=
- mitterange ülemhulk ehk kas teine hulk on saadud esimesest elemente eemaldades või sellega võrdne
Proovi järgi, kuidas need operatsioonid töötavad!
Hulga video
https://panopto.ut.ee/Panopto/Pages/Viewer.aspx?id=2cef9cde-0094-4bea-9bab-ac6000af129a
Järjendi, enniku ja hulga video
https://panopto.ut.ee/Panopto/Pages/Viewer.aspx?id=dee3d5b0-2865-4d01-b7ce-ac61005325e7
Enesekontroll
Kasutatud allikad: