Zanka "za vsakega"
Med nalogami iz prejšnje "lekcije" je bila ena na temo računanja poprečne teže treh oseb, Ane, Berte in Cilke. Če vzamemo, da imamo šest oseb in če izpustimo vnašanje podatkov, bi lahko bil program tak.
To ni posebej praktično. Če bi morali namesto tega poiskati najtežjo osebo, bi bil program že naravnost odvraten.
Če bi imeli teže stotih ljudi ... ne, tako ne gre.
Povejmo po domače: pripraviti bi morali seznam tež vseh študentov in seštevati stvari s seznama, iskati največjo stvar na seznamu... in tako naprej. V resnici pravzaprav niti nismo povedali po "kar tako, po domače", tudi v resnici naredimo natančno to.
Seznami
Seznam tež zapišemo takole:
Seznam (angl. list) v resnici nekoliko spominja na niz: niz je
zaporedje znakov, ki ga zapišemo tako, da ga zapremo v narekovaje. Seznam
je zaporedje česarkoli, recimo števil, lahko pa tudi česa drugega. Števila
ali kaj drugega naštejemo, vmes pišemo vejice in vse skupaj zapremo v
oglate oklepaje ([
in ]
). Za primer sestavimo še
seznam imen študentov
in seznam, ki bo povedal, ali gre za študenta ali študentko
S seznami se da delati ogromno reči. Nek drug pomemben jezik, Lisp, tako
temelji na seznamih, da je po njih dobil celo ime (list processor). Tu
jih bomo spoznali samo v povezavi z zanko for
.
Zanka for
Python ima dve vrsti zank: zanki while
dela družbo
for
. Medtem ko while
nekaj počne, dokler velja
določen pogoj, je for
veliko preprostejša.
Zastavimo si preprosto (in ne čisto smiselno) nalogo: izpišimo teže in kvadrate tež vseh študentov na seznamu. Se pravi (po slovensko)
V Pythonu pa prav tako, samo brez sklonov:
V zanki for
se skriva prirejanje. Zanka najprej
priredi spremenljivki teza
prvi element seznama
teze
. Nato se izvrši vsa koda bloka znotraj bloka
for
- tako, kot se je dogajalo v zanki while
.
V naslednji rundi priredi spremenljivki teza
drugi element in spet izvede kodo znotraj bloka, ...
ter tako naprej do konca seznama.
Zdaj pa izpišimo vse teže, ki so večje od 70.
Napišimo program, ki pove, kako težak je najlažji študent.
Je potrebno prevesti v slovenščino? Pa dajmo.
Deluje ta program samo na seznamih števil? Ali pa bi znal poiskati tudi najmanjši niz? Kako pravzaprav primerjamo nize? Nize primerja, seveda, po abecedi. In, da, program deluje tudi na nizih, vrne "najmanjši" niz - prvi niz po abecedi.
Mimogrede, Python ima že vdelano funkcijo min
, ki vrne
najmanjši element seznama.
Kako bi izračunali vsoto elementov seznama?
Pa poprečno vrednost? Za to moramo poznati dolžino seznama. Pove nam jo
funkcija len
(okrajšava za length, če ji kot argument
podamo nek seznam).
Samo... malo previdni moramo biti. Seznam bi lahko bil tudi prazen. Dogovorimo se, da bo poprečna vrednost v tem primeru 0. Pravilno delujoč program bi bil takšen.
Štetje
Če hočemo šteti od 10 do 20, to naredimo - še znamo? - z zanko
while
.
Tole je malček nerodno. Štetje je tako pogosta reč, da bi bilo koristno,
če bi obstajala zanj bližnjica. In seveda obstaja. Funkcija
range(10, 20)
sestavi seznam števil od 10 do 19. Hmnja, ja.
Spodnja meja je vključena, zgornja ne. Če hočemo od 10 do 20, moramo uporabiti
range(10, 21)
. (Čemu služi ta nekonsistentnost? V resnici je zelo
uporabna. To je ena boljših stvari v Pythonu. Razlaga, zakaj je to tako super,
pa bi spet presegala čas našega druženja.)
Če bi torej hoteli izpisati števila od 10 do 20, bi to z zanko
for
naredil takole:
Po slovensko: za vsako število i od 10 do 21 naredi tole: izpiši ga.
Ker pogosto štejemo od 0, imamo za to bližnjico. Namesto, recimo,
range(0, 8)
pišemo kar range(8)
. Tako bo
izpisal števila od 0 do 7. Torej 8 števil. Velikokrat štejemo tudi le
zato, da nekaj ponovimo toliko in tolikokrat. Samega "števca", i
,
niti ne potrebujemo. Tako bi, recimo
osemkrat napisal Ana.
Iskanje po seznamih
Za konec tega bežnega srečanja z zankami, spoznajmo nekaj, kar brucom programiranja pogosto dela težave - gre pa za lep primer tega, kako mora vrteti svoje misli programer.
Lihi - sodi
Kako bi ugotovili, ali vsebuje seznam kako sodo število? Tako kot prej si bomo izmislili seznam nekih števil (in program preskušali tako, da ga bomo spreminjali).
V začetku si rečemo, da nimamo nobenega sodega števila. Nato gremo prek vseh števil in čim naletimo na kakega sodega, zabeležimo, da smo, aleluja, našli sodo število.
Ne naredite klasične napake. Tole je narobe:
Ta program se bo ob vsakem lihem številu delal, da doslej ni bilo še
nobenega sodega - zaradi imamo_sodo = False
bo pozabil, da je
kdajkoli videl kako sodo število. V gornjem seznamu bo, recimo, pregledal
vsa števila, končal bo s 13 in si ob tem rekel imamo_sodo = False
.
Rezultat bo tako napačen.
Kako pa ugotovimo, ali ima seznam sama soda števila?
Spet bomo naredili podobno napako kot prej, če bomo pisali
Program že takoj, ko vidi 1, ugotovi, da niso vsa števila v seznamu soda,
in postavi sama_soda = False
. Vendar melje seznam naprej in ob
vsakem koraku znova nastavlja sama_soda
. Ko pride do 42, postavi
sama_soda
na True
. To pa je ravno zadnje število;
sama_soda
ostane True
... pa smo tam.
Mimogrede, rezultat tega programa je znan že, čim naletimo na prvo liho število. Torej bi bilo čisto vseeno, če računalnik v tistem trenutku neha pregledovanje. To mu v resnici lahko naročimo.
Ukaz break
pomeni, da želimo prekiniti zanko. Program skoči
"ven" iz zanke in nadaljuje z izvajanjem ukazov, ki sledijo zanki.
Praštevila
Napisati želimo program, ki pove, ali je dano število praštevilo. Tole je zelo podobno programu, ki išče sama soda števila. Drugačen je le pogoj: namesto, da bi preverjali, ali je število deljiNaredili bi lahko takole:
V začetku predpostavimo, da je število praštevilo
(je_prastevilo = True
). Nato gremo prek števil od 2 do n
(for i in range(2, n)
); če naletimo na delitelj števila, ki
ga je vpisal uporabnik, (if n % i == 0
) si zapomnimo, da to
število ni praštevilo (je_prastevilo = False
) in končamo zanko
(break
).
Povemo lahko celo, kateri je najmanjši delitelj tega števila.
Ko smo zanko prekinili, je i
ostal, kakršen je bil. Če je na
koncu enak n-1
, vemo, da se je zanka iztekla do konca, število
n-1 pa navadno ni delitelj n-ja ... razen, če je n enak 2. No, v tem
primeru je stvar še hujša: če je n enak 2, se zanka ne izvede in i sploh
ni definiran. Naš program za 2 sploh ne deluje. Popravite ga sami. ;)