Arvutiteaduse instituut
  1. Kursused
  2. 2024/25 sügis
  3. Programmeerimine (LTAT.03.001)
EN
Logi sisse

Programmeerimine 2024/25 sügis

  • Üldinfo
  • 1. Muutuja ja avaldis
1.1 Alustamine Thonnyga
1.2 Pythoni põhimõisted
1.3 Kodutöö
1.4 Harjutused
1.5 Silmaring. Standardteek ja moodulid
  • 2. Tingimuslause
  • 3. Funktsioon
  • 4. Korduslause
  • 5. Sõned. Lihtsam failitöötlus
  • 6. Kontrolltöö 1
  • 7. Järjend
  • 8. Järjend 2
  • 9. Kahekordne tsükkel. Failitöötlus
  • 10. Andmestruktuurid
  • 11. Andmestruktuurid 2
  • 12. Kontrolltöö 2
  • 13. Objektorienteeritud programmeerimine
  • 14. Objektorienteeritud programmeerimine 2
  • 15. Rekursioon
  • 16. Kordamine. Projektide esitlused
  • Viiteid
  • Silmaringimaterjalid
  • Materjalid

Silmaring. Standardteek ja moodulid

Õpiku esimeses peatükis sai uuritud math moodulit ning selle funktsioone ja konstante. Pythonis on palju rohkem selliseid mooduleid erinevate probleemide lahendamiseks.

Näiteks:

  • Kuidas saada kätte homne kuupäev? Kuu lõpus võib muutuda küsimus väga keeruliseks, kui seda ise üritada arvutada. Mitu päeva on praeguses kuus? Veebruari lõpus: kas on liigaasta?
  • Kuidas panna elemendid juhuslikku järjekorda?
  • Kuidas uurida kausta sisu Pythoniga?
  • Kuidas muuta faili nimesid?

Pythonisse sisse ehitatud moodulid teevad lahendused sellistele küsimustele lihtsaks. Selles peatükis vaatame mõne huvitavama mooduli kasutamise näited. Uurime, kuidas moodulid üldse töötavad ja kuidas teha enda lihtne moodul.

Ettevalmistus

Selle peatüki läbimiseks piisab Pythoni installatsioonist ning õpiku esimese peatüki lugemisest. Väikesel määral käsitletakse andmestruktuure, mida pole veel tutvustatud.

Et kõigest aru saada, on soovitatav tutvuda funktsioonidega (peatükk 4) ja järjenditega (peatükk 7).

Moodulite importimine

Tuletame kõigepealt meelde, kuidas mooduleid importida. Seda saab teha import lause abil:

>>> import math
>>> math.cos(math.pi)
-1.0

Moodulitele saab anda ka nimesid as lausega. Seda tehakse pigem harva ja pikemate või väga sagedasti kasutatavate nimedega. Tavaks on lühendada pandas moodul pd-ks ja numpy moodul np-ks.

>>> import math as m
>>> m.cos(m.pi)
-1.0

Moodulitest saab importida ainult vajalikud muutujad kasutades from lauset. Tervet moodulit sellega ei impordita. Mitu muutujat saab eraldada komaga.

>>> from math import pi, cos
>>> pi
3.141592653589793
>>> cos(pi)
-1.0
>>> math.pi
NameError: name 'math' is not defined

Tärni abil saab importida kõik mooduli muutujad.

>>> from math import *
>>> pi
3.141592653589793
>>> e
2.718281828459045
>>> tau
6.283185307179586
>>> cos(pi)
-1.0

Standardteek

Pythoniga tuleb kaasa palju mooduleid, mida nimetatakse kollektiivselt standardteegiks. Nende täisnimekiri on saadaval Pythoni dokumentatsioonis, aga vaatame lähemalt mõnda huvitavamat.

Moodul math

Selle mooduli abil saab ligi matemaatilistele funktsioonidele, mida Pythonis vaikimisi ei ole. Täisdokumentatsioon: https://docs.python.org/3/library/math.html 

Importimine:

>>> import math

Kasulikud konstandid ja funktsioonid:

>>> math.pi  # pii
3.141592653589793
>>> math.inf  # lõpmatus (kõik arvud on võrdlemisel sellest väiksemad)
inf
>>> math.floor(1.7)  # alla ümardamine
1
>>> math.ceil(1.3)  # üles ümardamine
2
>>> math.sqrt(2)  # ruutjuur
1.4142135623730951
>>> math.factorial(6)  # faktoriaal
720
>>> math.log(128, 2)  # logaritmid
7.0
>>> math.cos(math.pi)  # trigonomeetria
-1.0
>>> math.isclose(1.45, 1.46, rel_tol=0.01)  # tõeväärtus, kas kaks arvu on lähestikku rel_tol piires
True

Mõned kasulikud matemaatilised funktsioonid on Pythonisse juba sisse ehitatud:

>>> round(1.7)  # ümardamine
2
>>> round(1.337, 2)  # kahe komakohani ümardamine
1.34
>>> abs(-5)  # absoluutväärtus
5
>>> 2**0.5  # ruutjuur ilma math moodulita
1.4142135623730951

Moodul random

Selle mooduliga saab genereerida pseudojuhuslikke arve, et tuua programmidesse juhuslikkust. Täisdokumentatsioon: https://docs.python.org/3/library/random.html 

Importimine:

>>> import random

Kasulikud funktsioonid:

>>> random.randint(1, 10)  # juhuslik täisarv kahe arvu vahel
7
>>> random.randint(1, 10)
10
>>> random.random()  # juhuslik ujukomaarv 0 ja 1 vahel
0.8426622092891721
>>> random.uniform(1.5, 3)  # juhuslik ujukomaarv kahe arvu vahel
1.9124507393369863
>>> pakk = ["ärtu", "ruutu", "poti", "risti"]
>>> random.choice(pakk)  # juhuslik valik järjendist
"ruutu"
>>> random.shuffle(pakk)  # järjendi segamine
>>> pakk
['ruutu', 'risti', 'poti', 'ärtu']

Moodul datetime

Selle mooduli abil saab käsitleda kuupäevi ja aegu. Siin näites luuakse objekte, millest räägitakse täpsemalt peatükis "Objektorienteeritud programmeerimine". Praeguseks olgu need lihtsalt keerulised muutujad, millega saab erinevaid asju teha. Täisdokumentatsioon: https://docs.python.org/3/library/datetime.html

Importimine:

>>> import datetime

Datetime objekti loomine (aasta, kuu, päev, tund, minut, sekund):

>>> kuupäev = datetime.datetime(2020, 2, 29, 12, 34, 56)
>>> kuupäev
datetime.datetime(2020, 2, 29, 12, 34, 56)
>>> kuupäev.year
2020
>>> kuupäev.second
56

Praeguse ajahetke saamine:

>>> praegu = datetime.datetime.now()
>>> praegu
datetime.datetime(2020, 2, 29, 18, 20, 33, 30651)

Datetime objekti vormindamine sõneks:

>>> praegu.strftime("%Y-%m-%d %H:%M:%S")
'2020-02-29 18:20:33'

Vormindamise märgendite nimekiri: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes 

Datetime objekti parsimine sõnest.

>>> datetime.datetime.strptime("2020-02-29 18:20:33", "%Y-%m-%d %H:%M:%S")
datetime.datetime(2020, 2, 29, 18, 20, 33)

Aegadele saab kestusi juurde liita ja maha lahutada, mille kaudu tekib uus datetime objekt. Liidame enne loodud kuupäevale juurde 13 tundi ja 37 minutit:

>>> kestus = datetime.timedelta(hours=13, minutes=37)
>>> kuupäev + kestus
datetime.datetime(2020, 3, 1, 2, 11, 56)
>>> kuupäev - kestus  # lahutada saab ka
datetime.datetime(2020, 2, 28, 22, 57, 56)

Seega homse kuupäeva saab kätte nii:

>>> homme = praegu + datetime.timedelta(days=1)
>>> homme
datetime.datetime(2020, 3, 1, 18, 20, 33, 30651)

Moodul os

Selle mooduliga saab ligi operatsioonisüsteemi funktsionaalsusele, näiteks failide asukohtadele.

Täisdokumentatsioon: https://docs.python.org/3/library/os.html

Importimine:

>>> import os

Praeguse tee (current working directory) saamine:

>>> os.getcwd()
'/home/kasutaja/Python/Moodulid/'

Failinimede järjendi saamine praeguses kaustas ja määratud kaustas:

>>> os.listdir()
['programm.py', 'pilt.jpg', 'Uus kaust', 'Lõputöö.pdf']
>>> os.listdir('/home/kasutaja/Python/Moodulid/Uus kaust')
['saladused.txt']

Failinime muutmine:

>>> os.rename("pilt.jpg", "foto.jpg")
>>> os.listdir()
['programm.py', 'foto.jpg', 'Uus kaust', 'Lõputöö.pdf']

Kausta loomine:

>>> os.mkdir("Teine kaust")
>>> os.listdir()
['programm.py', 'foto.jpg', 'Uus kaust', 'Lõputöö.pdf', 'Teine kaust']

Proovi kirjutada programm, mis loeb sisse kausta kõik failid ja väljastab nende sisu. Siin tuleb kasuks for-tsükkel. Katseta seda kaustaga, mis sisaldab tekstifaile.

Moodul sys

Selle mooduliga saab ligi süsteemipõhisele funktsionaalsusele. Täisdokumentatsioon: https://docs.python.org/3/library/sys.html 

Importimine:

>>> import sys

Käsurea argumentidele saab ligi `sys.argv` muutujast:

>>> sys.argv
['programm.py', 'esimene', 'teine']

Selline väärtus tuleb, kui käivitada Thonnys `programm.py` järgmise käsuga:

>>> % Run programm.py esimene teine

Või käsurealt:

kasutaja@arvuti ~/Python/Moodulid$ python3 programm.py esimene teine
C:\Users\kasutaja\Python\Moodulid> python3 programm.py esimene teine

Täisarvu maksimaalne väärtus praeguses arvutis:

>>> sys.maxsize
9223372036854775807

Pythoni interpretaatori versiooni saamine:

>>> sys.version
'3.7.6 (default, Jan 19 2020, 22:34:52) \n[GCC 9.2.1 20200117]'

Programmi töö lõpetamine:

>>> sys.exit("Põhjus")

Moodul turtle

Siia lõppu ka midagi lõbusat õhtutundideks.

Pythoni standardteegis on tore moodul nimega turtle, mis võimaldab algajatel Pythoniga lihtsaid joonistusi ja skeeme koostada. Järgnevalt mõned käsud, mida võiks proovida:

forward(100) – liigu 100 sammu edasi
backward(100) – liigu 100 sammu tagasi
right(90) – pööra 90 kraadi paremale
left(90) – pööra 90 kraadi vasakule
up() – ära enam joonista (pliiats tõstetakse üles)
down() – hakka joonistama (pliiats lastakse alla)
speed(1000) – muuda joonistamise kiirust vahemikus 1-10. 0 on maksimumkiirus.
# – kommenteeri rida välja. Trellidega algavat rida ei käivitata ja võib kasutada kommenteerimiseks.

Veel käske: https://docs.python.org/3/library/turtle.html

Ennusta ja proovi, mida teeb allolev näidisprogramm:

from turtle import *

forward(100)
right(90)
forward(100)

Kilpkonnagraafika joone värvimine

Proovime nüüd teha programmi natukene lõbusamaks- lisame värve. Pliiatsi värvi on võimalik muuta nii: color("värvinimi"). Näiteks käsku color("red") saaks kasutada punase joone tegemiseks nii:

color("red")
forward(100)

Värve saab veel selliselt: color("#285078"), kus värvikoodi saab näiteks guugeldades "color codes".

Kujundi seest värvimine

Lisaks on võimalik kujundeid ka seest värvida. Selleks, et ruut seest punaseks värvida, tuleks panna ruudu joonistamisel selle ette käsud color("red") ja begin_fill() ja pärast joonistamist käsk end_fill().

Proovi nüüd teha näiteks jõulukaart, kus on ehitud kuusepuu.

Pykkar

Pykkar on virtuaalne robot, kes tegutseb oma virtuaalses maailmas. Ta suudab liikuda, ruute värvida, asju kanda ja tal on andurid mitmesuguste objektide tuvastamiseks. Pykkar on realiseeritud moodulis pykkar (see ei ole Pythoni põhimoodul, seega pead selle tõenäoliselt installima: Thonnys vali Tööriistad → Halda lisapakke... või Tools → Manage Packages ... ning otsi sealt pykkar).

Proovige esimest programminäidet:

from pykkar import *
create_world("""
########
#  >   #
#      #
#      #
#      #
#      #
########
""")
step()
step()
step()
right()

See programm peaks kuvama väljaku koos liikuva robotiga:

Pykkar mõistab järgmisi käsklusi:

  • step() – tee samm edasi.
  • right() – pööra 90° paremale.
  • take() – korja üles järgmisel ruudul olev koonus. Pykkar suudab transportida ühte koonust korraga.
  • put() – pane koonus järgmisele ruudule. Ühel ruudul võib asuda kuni 9 koonust.
  • push() – lükka Pykkari ees olevat kasti või koonust.
  • paint() – värvi jooksev ruut tumedaks.
  • is_wall() – ütleb, kas ees on sein (tagastab True või False).
  • is_cone() – ütleb, kas ees on koonus.
  • is_box() – ütleb, kas ees on kast.
  • is_painted() – ütleb, kas jooksev ruut on värvitud.
  • get_direction() – küsib jooksvat suunda (tagastab 'N', 'E', 'S' või 'W').

Pykkari maailm luukase funktsiooniga create_world, millele antakse argumendina ette mitmerealine sõne. Sõne kirjeldab maailma kaarti, iga sümbol tähistab ühte ruutu.

Ruutude tüübid on järgmised:

SümbolTähendusNäide
(tühik)Hele ruut
.Tume ruut
#Sein
^ > v <Pykkar heledal ruudul, nool näitab suunda
N E S WPykkar tumedal ruudul, täht näitab suunda
1 2 ... 9Koonuste arv heledal ruudul
CÜks koonus tumedal ruudul
bKast heledal ruudul
BKast tumedal ruudul

Moodul this

Selle mooduli importimine väljastab Pythoni põhimõtted (The Zen of Python). Proovi seda importida.

Moodul antigravity

Seda proovi ise importida. :)

Kuidas moodulid töötavad?

Importisime palju erinevaid mooduleid ja kasutasime nende konstante ja funktsioone, aga kuidas need üldse töötavad? Kuidas luua ise üks moodul?

Mooduli importimine tegelikult otsib üles sellenimelise Pythoni faili ja käivitab selle. Kõiki mooduli failis defineeritud muutujaid saab importivas programmis kasutada.

Isetehtud moodul

Proovime ise mooduli teha. Kirjutame programmi minumoodul.py, kus defineerime ühe konstandi ja lihtsa funktsiooni. Lisame ka ühe print-lause, et tõestada, kuidas kogu programm käivitub.

konstant = "Tere"

def ruut(n):
    return n**2

print("Moodul imporditud!")

Nüüd avame samas kaustas interpretaatori või loome uue Pythoni faili ja proovime tehtud moodulit importida ning muutujaid kasutada.

>>> import minumoodul
Moodul imporditud!
>>> minumoodul.konstant
'Tere'
>>> minumoodul.ruut(17)
289

Kõik muutujad töötavad ning sõnum väljastatakse. Üldiselt välditakse moodulite importimisega millegi väljastamist. Teised moodulid ju seda ei teinud.

Mooduli kõikide muutujate loetlemiseks on olemas sisseehitatud funktsioon dir(). Kui sulud tühjaks jätta, näidatakse kõiki muutujaid, mis on kogu programmis, s.h imporditud moodulid. Kui sulgude sisse panna muutuja, siis loetletakse selle muutujaga seotud muutujaid.

>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'math', 'minumoodul']
>>> dir(minumoodul)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'konstant', 'ruut']
>>> dir(math)  # kui on imporditud
['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']

Kui kunagi satub ette võõras muutuja, on mõistlik jooksutada selle peal dir() funktsioon, et näha kõiki selle võimalusi. Katseta ka help() funktsiooni.

Saame ka uurida erinevate objektide funktsioone ja muutujaid. Vaatame eelnevalt mainitud datetime objekti võimalusi.

>>> from datetime import datetime
>>> praegu = datetime.now()
>>> dir(praegu)
['__add__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__radd__', '__reduce__', '__reduce_ex__', '__repr__', '__rsub__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', 'astimezone', 'combine', 'ctime', 'date', 'day', 'dst', 'fold', 'fromisocalendar', 'fromisoformat', 'fromordinal', 'fromtimestamp', 'hour', 'isocalendar', 'isoformat', 'isoweekday', 'max', 'microsecond', 'min', 'minute', 'month', 'now', 'replace', 'resolution', 'second', 'strftime', 'strptime', 'time', 'timestamp', 'timetuple', 'timetz', 'today', 'toordinal', 'tzinfo', 'tzname', 'utcfromtimestamp', 'utcnow', 'utcoffset', 'utctimetuple', 'weekday', 'year']
>>> praegu.year
2020

Leia vastused küsimustele:

  • Mida teeb help() funktsioon?
  • Millised funktsioonid ja konstandid on re moodulil?
  • Millised funktsioonid ja muutujad on timedelta objektil?

Moodulite asukohad

Kirjutasime enda mooduli interpretaatoriga samasse kausta ja saime seda importida, aga muud moodulid ei asu selles kaustas ja neid saab ikka importida. Kus need asuvad?

Pythonil on erinevate moodulite asukohtadest nimekiri nimega path. Sellele saab ligi mooduli sys muutujast.

>>> import sys
>>> sys.path
['', '/usr/lib/python37.zip', '/usr/lib/python3.7', '/usr/lib/python3.7/lib-dynload', '/home/kasutaja/.local/lib/python3.7/site-packages', '/usr/local/lib/python3.7/dist-packages', '/usr/lib/python3/dist-packages', '/usr/lib/python3.7/dist-packages']

Mooduli importimisel otsitakse need kaustad järjest läbi, alustades esimesest. Esimene kaust on tühisõne ehk esimesena vaadatakse üle kaust, kus programm käivitati.

Imporditud moodulite failide asukohta saab ka näha:

>>> import turtle
>>> turtle
<module 'turtle from '/usr/lib/python3.7/turtle.py'>
>>> turtle.__file__
'/usr/lib/python3.7/turtle.py'

Mõned moodulid on Pythoni lähtekoodi sisseehitatud ja nende lähtekoodile nii lihtsalt ligi ei pääse.

>>> import math
>>> math
<module 'math' (built-in)>
>>> math.__file__
AttributeError: module 'math' has no attribute '__file__'

Proovi uurida moodulite this ja antigravity lähtekoode. Kas need vastavad ootustele?

Kas programm käivitati või imporditi? Igal programmil (ja seega moodulil) on muutuja __name__ (kaks alakriipsu ees ja taga), mille väärtuseks on mooduli nimi sõnena. See muutuja on ka käivitataval programmil, aga selle väärtus on siis hoopis "__main__".

>>> __name__
'__main__'

Kui __name__ väärtuseks on mooduli nimi, siis järelikult programm imporditi. Kui selle väärtus on "__main__", siis see käivitati.

Tihti lisatakse programmi ette if-lause kontrolliga, kas programmi käivitati. Nii saavad teised arendajad programmi importida ja selle funktsioone kasutada ilma, et programmi põhiosa käivitub.

if __name__ == "__main__":
    print("Programm käivitati, ei imporditud!")

Proovi seda järele minumoodul.py programmis.

Enesekontrolliküsimused

Ülesanded

Ülesanne 1

Muuda minumoodul.py programmi nii, et see väljastab sõnumi ainult siis, kui see käivitatakse. Importimisel ei tohi midagi väljastada.

>>> %Run minumoodul.py
Programm käivitati, ei imporditud!
>>> import minumoodul
>>> 

Ülesanne 2

Kirjuta programm, mis võtab käsurealt sisendiks päevade arvu ning väljastab kuupäeva ja aja pärast sisestatud päevade arvu.

Näide:

>>> %Run ajaarvutaja.py 1337
Praegune aeg on 2020-02-29 18:20:33.
1337 päeva pärast on aeg 2023-10-28 18:20:33.

Ülesanne 3

Google Mapsi koordinaatsüsteemi laiuskraadide piirid on -85 kuni +85 ning pikkuskraadide piirid on -180 kuni +180. Et minna Google Mapsi rakenduses mingitele koordinaatidele, saab minna veebilehitsejaga aadressile https://maps.google.com/?q=laiuskraad,pikkuskraad. Näiteks Delta hoone puhul https://maps.google.com/?q=58.385894,26.725829.

Kirjuta programm, mis genereerib juhusliku koordinaadipaari ja avab veebilehitsejaga selle asukoha Google Mapsis. Veebilehitseja peaks avama lehekülge samamoodi, nagu seda teeb antigravity moodul. Programmi koodi kirjuta kommentaar huvitava asukohaga, kuhu see sind viis.

4. Kirjuta programm, mis kasutab asjalikult kolme erineva mooduli funktsionaalsust. Võib kasutada mooduleid, mida materjalides ei ole käsitletud.

  • Arvutiteaduse instituut
  • Loodus- ja täppisteaduste valdkond
  • Tartu Ülikool
Tehniliste probleemide või küsimuste korral kirjuta:

Kursuse sisu ja korralduslike küsimustega pöörduge kursuse korraldajate poole.
Õppematerjalide varalised autoriõigused kuuluvad Tartu Ülikoolile. Õppematerjalide kasutamine on lubatud autoriõiguse seaduses ettenähtud teose vaba kasutamise eesmärkidel ja tingimustel. Õppematerjalide kasutamisel on kasutaja kohustatud viitama õppematerjalide autorile.
Õppematerjalide kasutamine muudel eesmärkidel on lubatud ainult Tartu Ülikooli eelneval kirjalikul nõusolekul.
Courses’i keskkonna kasutustingimused