Keerukamad tingimused
Mõnikord on meil tarvis kontrollida tingimust, mis koosneb mitmest osast. Olgu näiteks seif, mis avaneb ainult siis, kui kaks erinevat koodi õigesti sisestatakse. Sellisel juhul oleks meil vaja kontrollida nii esimese kui teise koodi õigsust. Selliseid alamtingimusi on võimalik kombineerida loogiliste tehete abil. Programmeerimise olulisemad loogilised tehted on and
, or
ning not
. Loogilisi tehteid kasutades moodustub loogiline avaldis, millel on tõeväärtus.
Loogilised tehted ja avaldised
Tehe and
Tehe and
on tavakeelse “ja” tähendusega. Tehte and
tulemus on tõene siis ja ainult siis, kui mõlemad avaldised (tehte operandid), mille vahel and
paikneb, on tõesed. Järgnevas programmis ongi seda ära kasutatud:
Näiteprogramm. Kahe koodiga seif
kood1 = "1234" kood2 = "0000" print("Sisesta 1. salakood:") pakutud_kood1 = input() print("Sisesta 2. salakood:") pakutud_kood2 = input() if pakutud_kood1 == kood1 and pakutud_kood2 == kood2: print("Seif avaneb!") else: print("Salakoodidega on kehvasti. Tõstke käed üles!")
Katseta seda programmi erinevate sisenditega. Näiteks, kui
- mõlemad koodid on õiged;
- 1. kood on õige, 2. kood vale;
- 1. kood on vale, 2. kood õige;
- mõlemad on valed.
Kas tulemus vastas teie ootustele?
Tehe or
Sõna “or” tähendab tõlkes “või”. Selgita välja, mida see meie jaoks programmis tähendab (selle tähendus erineb pisut tavakeelsest tähendusest). Asenda eelmise programmi valikulauses tehe and
tehtega or
:
if pakutud_kood1 == kood1 or pakutud_kood2 == kood2:
Katseta nüüd programmi tööd erinevate sisenditega, nimelt kui
- mõlemad koodid on õiged;
- 1. kood on õige, 2. kood vale;
- 1. kood on vale, 2. kood õige;
- mõlemad on valed.
Eelmise näite puhul olid välja pakutud mõned variandid, mida katsetamisel kasutada. Need polnud valitud suvaliselt, vaid püüdsid hõlmata kõiki põhimõtteliselt erinevaid variante. Testimine on programmeerimises väga oluline. Vähegi suurema programmi puhul on mõistlike testide koostamine omaette suur töö.
Tehe not
Tehe not
“pöörab” tõeväärtuse vastupidiseks. Näiteks avaldise
not 1 == 1
väärtus on False
, sest 1 == 1 väärtus on True
.
Loogiliste tehete kokkuvõte
Tehete and
ja or
puhul on meil vaja kahte operandi, millega tehe toimub. Selliseid tehteid nimetatakse kahekohalisteks ehk binaarseteks. Tehe not
töötab ühe operandiga (on ühekohaline ehk unaarne).
Loogiliste tehete and
, or
ja not
kasutamisel on tulemused järgnevad:
väide1 and väide2
– tõene ainult siis, kui mõlemad väited on tõesedväide1 or väide2
– tõene siis, kui vähemalt üks väidetest on tõenenot väide1
– tõene ainult siis, kui väide1 on väär.
Sealjuures on iga väide avaldis tõeväärtusega True
või False
, mis võib “pärineda” ka mingisugusest võrdlemistehtest (nt pakutud_kood1 == "1234"
, vanus < 14
) või ka loogilisest tehtest (seda vaatame varsti).
Tehted ja avaldised on meile põhimõtteliselt tuttavad juba koolimatemaatikast. Loogilised tehted ja avaldised vajavad veidi harjumist. Ärge väga muretsege, kui esimese hooga kõik veel selgeks ei saa.
Loogilised avaldised muutuvad tingimusteks, kui neid selles rollis kasutatakse – näiteks tingimuslauses.
Üherealised tingimuslaused
Tingimuslauseid saab kirja panna ka lühendatult üherealisena. Selleks saab kasutada konstruktsiooni if tingimus: tegevus
Näiteks:
vanus = int(input("Sisesta vanus: ")) if vanus >= 18: print("Täisealine")
Lisaks saab lisada ka else-osa konstruktsiooniga esimene_tegevus if tingimus else teine_tegevus Näiteks:
vanus = int(input("Sisesta vanus:")) print("Täisealine") if vanus >= 18 else print("Alaealine")
Veel üks näide muutujale väärtuse andmisest, millest proovi iseseisvalt katsetades aru saada:
lülijalgne = "ämblik" if jalgade_arv == 8 else "putukas"
Keerulisem tingimus
Vahel on tingimused keerulisemad ja programmi korraliku töö huvides tuleb need põhjalikult läbi mõelda. Olgu meil tahtmine teha salatit – kartuli- või makaronisalatit. Lihtsustatult oleks meil vaja kartuleid või makarone ja salatikastet.
Jätame praegu täpsustamata, millest see salatikaste tehtud on ja muid detaile ka. Tegelikult kipubki päriselu loogilistes avaldistes kirjeldamine küllaltki keeruline olema. Programmide kirjutamisel tuleb seetõttu teha mõningaid lihtsustusi.
Loogilise avaldise koostamiseks võtame kasutusele muutujad kartul_olemas
, makaron_olemas
ja salatikaste_olemas
. Vastavalt sellele, kas koostisosa on olemas või mitte, on selle muutuja väärtus True
(on olemas) või False
(ei ole olemas).
Püüame nüüd kirja panna, kas saame salatit teha või mitte. Siin on tegelikult mitu võimalikku mõttekäiku ja ka avaldis võib lõpuks tulla (näiliselt) erinev.
Üks võimalus oleks mõelda nii, et meil on vaja kahte koostisosa: n-ö nimiosa ja salatikastet. Nimiosas võib olla kartul või makaron – panemegi kirja kartul_olemas
or makaron_olemas
. Sellele lisame salatikastme – (kartul_olemas or makaron_olemas) and salatikaste_olemas
. Sulud tähistavad siin (nagu ka aritmeetikas ja algebras) seda, et vastav tehe sooritatakse enne välimisi.
Järgmises näites on meil olemas kartul ja salatikaste, aga makarone pole. Kui meie mõttekäik on õige olnud, siis peaks ekraanile tulema True, sest tõesti saame salatit teha. Proovi järele!
Näiteprogramm. Salati võimalikkuse kontroll
kartul_olemas = True makaron_olemas = False salatikaste_olemas = True print((kartul_olemas or makaron_olemas) and salatikaste_olemas)
Proovi nüüd programmi tööd muutujate kartul_olemas
, makaron_olemas
ja salatikaste_olemas
erinevatel väärtustel. Enne käivitamist mõtle, milline tulemus oleks ootuspärane. Kas programm töötab vastavalt ootustele?
Tehete järjekord loogilises avaldises
Eelnevalt mainisime, et sulgude kasutamine suunab tehete järjekorda: sulgudes olev tehakse varem. Mis aga juhtuks, kui näiteks avaldises (a or b) and c
sulud ära jätaksime? Kas siis nagunii ei tehtaks siin or
-tehet enne, sest see asub eespool?
Tõepoolest on sulud siin olulised, sest nende puudumisel tehtaks esimesena hoopis and
-tehe. Nimelt on kokkulepe, et and
on kõrgema prioriteediga kui or
, analoogiliselt tavalise aritmeetikaga, kus korrutamine tehakse enne liitmist. Näiteks 2 + 3 * 4 on 14, aga mitte 20.
Käsklused match
ja case
Peatükis 2.1 Tingimuslause vaatlesime näidet, kus oli üksteise all palju erinevaid tingimusi:
minu_Suurus = input("Mis suuruses pusasid sa kannad (L,M,S)? ") if minu_Suurus.upper() == "L": print("Pusa on sulle liiga väike!") elif minu_Suurus.upper() =="M": print("Pusa on sulle paras!") elif minu_Suurus.upper() =="S": print("Pusa on sulle liiga suur!") else: print("Sellist suurust pole")
Tingimuslause peatüki boonusosana vaatame nüüd üht lisavõimalust sellise programmi koostamiseks. Alates Pythoni versioonist 3.10 on seda programmi võimalik pannakirja ka match
-case
abil:
minu_Suurus = input("Mis suuruses pusasid sa kannad (L,M,S)? ").upper() match minu_Suurus: case "L": print("Pusa on sulle liiga väike!") case "M": print("Pusa on sulle paras!") case "S": print("Pusa on sulle liiga suur!") case _: print("Sellist suurust pole")
Video loogilistest avaldistest
Video tehete järjekorrast ja avaldiste samaväärsusest
Failist lugemine reakaupa
Nüüd õpime ära ühe viisi tekstifailidest sisendi lugemiseks. Alustuseks koosta ja salvesta tekstifail nimega andmed.txt, mille esimesel real on inimese nimi, teisel real vanus (täisarvuna) ning kolmandal real e-maili aadress (lihtsuse mõttes ära praegu täpitähti kasuta). NB! See peab olema plain-text kujul, st Wordi fail ei sobi, faili võib luua Thonnys. Seejärel salvesta loodud failiga samasse kausta järgnev Pythoni programm ning käivita see.
f = open('andmed.txt') nimi = f.readline() vanus = f.readline() aadress = f.readline() print("Nimi:", nimi) print("Vanus:", vanus, "aastat") print("Aadress:", aadress) f.close()
Selgituseks
- Käsk open otsib failisüsteemist üles soovitud faili ja tagastab viite sellele (antud näites salvestasime selle viite muutujasse f, mis on levinud nimi failide tähistamiseks). NB! Kui on antud ainult failinimi ilma teeta, siis otsitakse seda ainult sellest kaustast, kus asub skript.
- Avaldis f.readline() loeb failist ühe rea ning annab selle sõnena. See käsk liigutab edasi ka failist lugemise järjehoidjat, st järgmisel korral sama käsku kasutades loetakse järgmine rida. See käsk on kaunis sarnane input käsuga, kuna kummalgi juhul ei tea me programmi kirjutades, millise konkreetse väärtuse me tulemuseks saame.
- f.close() ütleb failisüsteemile, et me oleme selle faili kasutamise lõpetanud.
Kui seda programmi katsetad, siis märkad, et väljundis tekib iga sisestatud andmejupi järele üks üleliigne tühi rida. Põhjus on just selles, et failist lugedes jäetakse iga rea lõppu alles ka reavahetuse sümbol (faili viimase rea puhul võib see puududa vastavalt sellele, kas failis on viimase rea lõpus reavahetus või mitte). Käsk print lisab omaltpoolt veel ühe reavahetuse.
Märkus
Kui Python ütleb sulle (Windowsi arvutis), et ta ei leia faili, aga sa oled veendunud, et fail on õiges kaustas olemas, siis tuleks kontrollida, ega failinimele pole saanud eksikombel kaks faililaiendit. Segadust võib tekitada asjaolu, et Windows Explorer varjab vaikimisi teatud faililaiendid.
Kõige kindlam on muuta Windowsi seadeid nii, et alati näidataks kõiki faililaiendeid. Selleks tuleks Windows Exploreris valida menüüribalt Tools -> Folder options… (kui menüüriba pole näha, siis vajutada korraks klahvi Alt). Avanenud dialoogis vali lehekülg View ning eemalda linnuke valiku Hide extensions for known file types eest.
Märkus
Kui proovid lugeda sisse täpitähtedega teksti, siis võib juhtuda, et saad veateate UnicodeDecodeError. Sel juhul tuleks open käsu rakendamisel öelda, millises kodeeringus on sinu tekst, nt open('andmed.txt', encoding='UTF-8'). 'UTF-8' asemel võid proovida ka 'cp1257'.
NB! Üleliigse reavahetuse saab ära võtta kasutades funktsiooni strip() näiteks selliselt: nimi = f.readline().strip(). Arvude puhul piisab arvuks teisendamisest näiteks täisarvu puhul selliselt vanus = int(f.readline()).