Podatkovne strukture
Do sedaj smo podatke v programu shranjevali s pomočjo spremenljivk in seznamov. S samo tema dvema načinoma shranjevanja podatkov lahko že rešimo vse možne izračunljive probleme. Python pa ima na voljo še veliko drugih načinov shranjevanja podatkov, ki so bolj primerni za določene probleme.
Terke (tuple)
Terke so podobne seznamom, le da jih ne moremo spreminjati. To pomeni, da jih lahko uporabljamo za shranjevanje podatkov, ki se ne bodo spreminjali. Terke so definirane z oklepaji () in elementi so ločeni z vejico ,. Do njihovih elementov dostopamo na enak način kot pri seznamih.
terka = (1, "Matej", True)
print(terka[0]) # 1
print(terka[1]) # Matej
print(terka[2]) # True
Pri seznamih se poskušamo izogibati različnim tipom elementov, pri terkah pa ponavadi shranjujemo različne tipe elementov. Terke so uporabne, kadar želimo shraniti več podatkov, ki so med seboj povezani. Na primer, če želimo shraniti podatke o osebi, lahko uporabimo terko.
oseba = ("Matej", "Urbas", 2000, "Ljubljana", True)
Terko lahko razpakiramo v več spremenljivk.
oseba = ("Matej", "Urbas", 2000, "Ljubljana", True)
ime, priimek, leto_rojstva, kraj_rojstva, je_student = oseba
print(ime) # Matej
print(priimek) # Urbas
Slovarji (dictionary)
Slovarji so podobni seznamom, le da imajo namesto indeksov ključe. Ključi so lahko poljubnega (hashable) tipa. Slovarji so definirani z zavitimi oklepaji {}. Ključ in vrednost sta ločena z dvopičjem :. Elementi so ločeni z vejico ,. Do elementov dostopamo z uporabo ključa.
slovar = {
"ime": "Matej",
"priimek": "Urbas",
"starost": 23
}
print(slovar["ime"]) # Matej
print(slovar["priimek"]) # Urbas
print(slovar["starost"]) # 23
print(slovar["naslov"]) # KeyError: 'naslov'
Dodajanje novega ali spreminjanje stareg elementa v slovar je zelo enostavno.
slov["naslov"] = "Tolmin"
Uporabne metode slovarjev
Slovarji imajo nekaj metod, ki nam olajšajo delo z njimi:
keys()- vrne seznam vseh ključev slovarjavalues()- vrne seznam vseh vrednosti slovarjaitems()- vrne seznam vseh parov (terk) ključ-vrednost slovarjaget(ključ)- vrne vrednost ključa, če obstaja, sicer vrneNoneget(ključ, privzeta_vrednost)- vrne vrednost ključa, če obstaja, sicer vrne privzeto vrednost
slovar = {
"ime": "Matej",
"priimek": "Urbas",
"starost": 23
}
print(slovar.keys()) # dict_keys(['ime', 'priimek', 'starost'])
print(slovar.values()) # dict_values(['Matej', 'Urbas', 23])
print(slovar.items()) # dict_items([('ime', 'Matej'), ('priimek', 'Urbas'), ('starost', 23)])
print(slovar.get("ime")) # Matej
print(slovar.get("naslov")) # None
print(slovar.get("naslov", "Tolmin")) # Tolmin
Množice (set)
Množice so neurejeni seznami unikatnih elementov. Množice so definirane z zavitimi oklepaji {}. Elementi so ločeni z vejico ,.
mnozica1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
mnozica2 = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
print(mnozica1.intersection(mnozica2)) # {5, 6, 7, 8, 9, 10}
print(mnozica1.union(mnozica2)) # {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
print(mnozica1.difference(mnozica2)) # {1, 2, 3, 4}
Z množicami lahko hitreje preverimo ali element obstaja v množici.
mnozica = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
print(1 in mnozica) # True
print(11 in mnozica) # False
To sicer zgleda enako kot pri seznamih, vendar je računska zahtevnost pri seznamu O(n), pri množici pa O(1). To pomeni, da je preverjanje ali element obstaja v množici veliko hitrejše kot pri seznamu. V podrobnosti se sicer ne bomo spuščali, temu je namenjeno več predmetov na fakulteti.
Tudi druge operacije z množicami so veliko hitrejše kot pri seznamih, imajo pa seveda nekaj omejitev:
- elementi množice morajo biti
hashable(števila, nizi, terke, …) - množica ne more vsebovati več enakih elementov
- zaporedje elementov v množici ni definirano
- …
Iteracija čez podatkovne strukture
Vse podatkovne strukture, ki smo jih spoznali, so iterable. To pomeni, da jih lahko uporabimo v zanki for.
seznam_terk = [("Matej", True), ("Lan", True), ("Luka", False)]
for element in seznam_terk:
print(element)
# ('Matej', True) <- izpiše terko
# ('Lan', True)
# ('Luka', False)
Elemente lahko razpakiramo v več spremenljivk kar v zanki for.
for ime, student in seznam_terk:
print(ime, student)
# Matej True <- prvi element je niz, drugi pa bool
# Lan True
# Luka False
Tako lahko hitro iteriramo tudi čez slovarje.
slovar = {
"ime": "Matej",
"priimek": "Urbas",
"starost": 23
}
# klic funkcije items() vrne seznam terk ključ-vrednost
for kljuc, vrednost in slovar.items():
print(kljuc, vrednost)
# ime Matej
# priimek Urbas
# starost 23
Iteracija čez slovar pa nam podaja ključe.
for kljuc in slovar:
print(kljuc)
print(slovar[kljuc])
# ime
# Matej
# priimek
# Urbas
# starost
# 23
Comprehension
Python ima zelo uporabno sintakso za ustvarjanje seznamov, ki se imenuje list comprehension. Z njim lahko ustvarimo seznam na zelo enostaven način. Podrobnosti je veliko, tukaj pa bomo predstavili le osnovno uporabo.
seznam = [i for i in range(5)]
kvadrati = [i ** 2 for i in range(5)]
print(seznam) # [0, 1, 2, 3, 4]
print(kvadrati) # [0, 1, 4, 9, 16]
List comprehension lahko uporabimo tudi za ustvarjanje slovarjev.
slovar = {i: i ** 2 for i in range(5)}
print(slovar) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
V list comprehension lahko dodamo še if stavek, s katerim lahko filtriramo elemente.
seznam = [i for i in range(10) if i % 2 == 0]
print(seznam) # [0, 2, 4, 6, 8]