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

Programmeerimine 2024/25 sügis

  • Pealeht
  • 1. Sissejuhatus
  • 2. Tingimuslause
  • 3. Tsükkel
  • 4. Järjend ja for-tsükkel
  • 5. Funktsioon
  • 6. Andmevahetus. Lihtne kasutajaliides
  • 7. Kahemõõtmeline järjend. Kahekordne tsükkel
  • 8. Kordamine 1. kontrolltööks?
  • 9. Kontrolltöö?
  • 10. Viitamine ja muteerimine
  • 11. Andmestruktuurid
  • 12. Rekursioon ja andmetöötlus
  • Projekti esitamine ja esitlused
  • 13. Objektorienteeritud programmeerimine
  • 14. Kordamine 2. kontrolltööks?
  • 15. Kontrolltöö 2?
  • Loengud
  • Moodle
  • Lahendus
  • Thonny paigaldamine
  • Thonny logide esitamine
  • Kiireksamist
  • Viited

13. OBJEKTORIENTEERITUD PROGRAMMEERIMINE

Sissejuhatus

Selles peatükis vaatame, kuidas andmeid saab hoida objektides. Vaatame, kuidas luua klasse, lisada sinna meetodeid ehk isendispetsiifilisi funktsioone, milleks on vaja konstruktorit ja kuidas kõike seda kasutada.

Objektis informatsiooni hoidmiseks peame läbi mõtlema, kuidas soovime objektis andmeid kirjeldada. Sarnaste objektide jaoks ühiste reeglite sätestamiseks kasutame klasse. Klassid ütlevad, millist infot me isendite kohta teame. Klassi defineerimiseks kasutatakse märksõna class. Sellele märksõnale järgneb klassi nimi ja koolon. Klasside nimed kirjutatakse suure algustähega ja peavad olema unikaalsed. Klassi sisu kirjutatakse taandega.

class Õppija:
    # klassi sisu

Muutujaid, mis kehtivad iga isendi enda kohta, nimetatakse isendimuutujateks ehk isendiväljadeks. Pythonis kasutatakse nende klassisiseseks eristamiseks märksõna self. Isendivälju saame kasutada selle märksõna kaudu.

Nõnda saame klassis Õppija defineerida muutujad self.matrikli_nr, self.eesnimi, self.perenimi ja self.isikukood. Klassist väljaspool nende muutujate kasutamisel kasutatakse self märksõna asemel vastavat isendit hoidva muutuja nime. self märksõna kasutatakse ka isendi informatsiooni kasutavate klassis defineeritud meetodite esimese argumendina. Nii võime öelda, et märksõna self on alati konstruktori ja meetodite argumentide hulgas esimene. Nüüd aga vaatame, kuidas luua konstruktorit ja meetodeid.

Konstruktor

Konstruktor on klassile iseloomulik meetod, kus defineeritakse isendimuutujad. Konstruktorit kasutatakse iga isendi loomisel isendimuutujate väärtustamiseks. Meetodi nimeks on __init__, mis tuleneb uue isendi initsialiseerimisest ehk lähtestamisest. Meetodi parameetriteks on esmalt märksõna self ning seejärel kõik teised muutujad, mida soovime isendisse salvestada. Konstruktori sees omistatakse need väärtused vastavatele isendimuutujatele ehk isendiväljadele. Argumendi ja isendimuutuja nimi ei pea olema sama, aga võib olla.

class Õppija:
    def __init__(self, matrikli_nr, eesnimi, perenimi, isikukood):
        self.matrikli_nr = matrikli_nr
        self.eesnimi = eesnimi
        self.perenimi = perenimi
        self.isikukood = isikukood

Isendite loomine

Uue isendi loomisel soovime isendimuutujad väärtustada ehk omistada neile mingid väärtused. Saame seda teha vastavalt sellele, millised isendimuutujad konstruktoris on. Meie näites on nendeks matrikli_nr, eesnimi, perenimi, isikukood.

õppur1 = Õppija("A034", "Albert", "Paas", 34105212737)
õppur2 = Õppija("A037", "Pearu", "Murakas", 34206122154)

print(õppur1.eesnimi)
 Albert

print(õppur2.eesnimi)
 Pearu

Sarnaselt üksikute muutujate lugemisele võime isendimuutujaid ka ümber väärtustada või lisada.

õppur1.lemmikloom = "koer"
print(õppur1.lemmikloom)

Väljastatakse "koer".

Meetodid

Klassis saame luua meetodeid, mis määravad objekti käitumise. Nii võime sama meetodi välja kutsuda mistahes Õppija isendi peal, saades isendi andmetest sõltuva tulemuse.

class Õppija:
    def __init__(self, matrikli_nr, eesnimi, perenimi, isikukood):
        self.matrikli_nr = matrikli_nr
        self.eesnimi = eesnimi
        self.perenimi = perenimi
        self.isikukood = isikukood

    def sugu(self):
        ik = str(self.isikukood)
        if int(ik[0]) % 2 == 1: # Kontrollib, kas isikukoodi 1. number on paaritu arv.
            return "M"
        else:
            return "N"

Meetodite väljakutsumine on sarnane sõnede peal split ja strip meetodite kasutusega:

print(õppur1.sugu())
 M

Meetod __str__

Kui soovime välja printida informatsiooni isendi kohta, siis üheks variandiks on üksikute isendiväljade kasutamine. print(õppur1) annab aga hetkel eriskummalise tulemuse <__main__.Õppija object at 0x02BFBE90> , mis ütleb, et tegu on isendiga klassist Õppija ning see asub mäluväljal 0x02BFBE90. Selleks, et print käsk annaks meile informatiivsema kirjelduse, tuleb klassis defineerida meetod __str__:

class Õppija:
    def __init__(self, matrikli_nr, eesnimi, perenimi, isikukood):
        self.matrikli_nr = matrikli_nr
        self.eesnimi = eesnimi
        self.perenimi = perenimi
        self.isikukood = isikukood

    def sugu(self):
        ik = str(self.isikukood)
        if int(ik[0]) % 2 == 1: # Kontrollib, kas isikukoodi 1. number on paaritu arv.
            return "M"
        else:
            return "N"

    def __str__(self):
        return "Õppija nimi: " + self.eesnimi + " " + self.perenimi
print(õppur1)
 Õppija nimi: Albert Paas

Veel muutujate defineerimisest

Klassis võib defineerida ka kõikidele sama klassi isenditele ühiseid muutujaid. Lisame meie näite konstruktorisse muutuja ülikool ja anname väärtuseks "Tartu Ülikool":

class Õppija:
    def __init__(self, matrikli_nr, eesnimi, perenimi, isikukood):
        self.matrikli_nr = matrikli_nr
        self.eesnimi = eesnimi
        self.perenimi = perenimi
        self.isikukood = isikukood
        self.ülikool = "Tartu Ülikool"

    def sugu(self):
        ik = str(self.isikukood)
        if int(ik[0]) % 2 == 1: # Kontrollib, kas isikukoodi 1. number on paaritu arv.
            return "M"
        else:
            return "N"

    def __str__(self):
        return "Õppija nimi: " + self.eesnimi + " " + self.perenimi

Loendamine

Me saame kasutada meetodeid ka selleks, et midagi loendada või arvulist suurust muuta. Meie näites võiksime iga kord, kui üliõpilane läbib aine, suurendada läbitud ainete muutuja väärtust ühe võrra. Selleks lisame muutuja läbitud_ainete_arv algväärtusega 0 ning loome meetodi läbi_aine, mis suurendab muutuja läbitud_ainete_arv väärtust ühe võrra.

class Õppija:
    def __init__(self, matrikli_nr, eesnimi, perenimi, isikukood):
        self.matrikli_nr = matrikli_nr
        self.eesnimi = eesnimi
        self.perenimi = perenimi
        self.isikukood = isikukood
        self.ülikool = "Tartu Ülikool"
        self.läbitud_ainete_arv = 0

    def sugu(self):
        ik = str(self.isikukood)
        if int(ik[0]) % 2 == 1: # Kontrollib, kas isikukoodi 1. number on paaritu arv.
            return "M"
        else:
            return "N"

    def läbi_aine(self):
        self.läbitud_ainete_arv += 1

    def __str__(self):
        return "Õppija nimi: " + self.eesnimi + " " + self.perenimi

Nüüd rakendame meetodit läbi_aine näiteks isendiga õppur1 kaks korda ja kui väljastame tema läbitud ainete arvu, saame 2.

õppur1.läbi_aine()
õppur1.läbi_aine()
print(õppur1.läbitud_ainete_arv)
 2

Isendid andmestruktuurides

Tähele võib panna ka võimalust panna isendeid teistesse andmestruktuuridesse nagu järjend.


õppurid = [õppur1, õppur2]
for el in õppurid:
    print(el.eesnimi, el.perenimi + ", isikukood:", el.isikukood)
 Albert Paas, isikukood: 34105212737
 Pearu Murakas, isikukood: 34206122154

Lõpetuseks

Oleme vaadelnud, kuidas ehitada objekt erinevate omadustega. Objekte on hea kasutada olukordades, kus ühe ja sama väärtusega on seotud hästi palju teisi. Õppija klassi asemel oleksime saanud kasutada ka näiteks kolme sõnastikku, kus ühes on matriklinumbrile vastav eesnimi, teises perekonnanimi, kolmandas isikukood. Ühendades kõik ühte isendisse muutub kood palju kergemini loetavaks ja hallatavamaks.

Näidiskoodi lõppkuju:

class Õppija:
    def __init__(self, matrikli_nr, eesnimi, perenimi, isikukood):
        self.matrikli_nr = matrikli_nr
        self.eesnimi = eesnimi
        self.perenimi = perenimi
        self.isikukood = isikukood
        self.ülikool = "Tartu Ülikool"
        self.läbitud_ainete_arv = 0

    def sugu(self):
        ik = str(self.isikukood)
        if int(ik[0]) % 2 == 1: # Kontrollib, kas isikukoodi 1. number on paaritu arv.
            return "M"
        else:
            return "N"

    def läbi_aine(self):
        self.läbitud_ainete_arv += 1

    def __str__(self):
        return "Õppija nimi: " + self.eesnimi + " " + self.perenimi

# Isendite loomine
õppur1 = Õppija("A034", "Albert", "Paas", 34105212737)
õppur2 = Õppija("A037", "Pearu", "Murakas", 34206122154)

# Ühe isendimuutuja info väljastamine
print(õppur1.eesnimi)
print(õppur2.eesnimi)

# Isendimuutuja tekitamine/muutmine ja vastava info väljastamine
õppur1.lemmikloom = "koer"
print(õppur1.lemmikloom)

# Isendimeetodi rakendamine
print(õppur1.sugu())

# Väljastamine, mis kasutab meetodit __str__
print(õppur1)
print(õppur2)

# Rakendame meetodit läbi_aine isendiga õppur1 kaks korda ja väljastame tema läbitud ainete arvu
õppur1.läbi_aine()
õppur1.läbi_aine()
print(õppur1.läbitud_ainete_arv)

# Isendid järjendis
õppurid = [õppur1, õppur2]
for el in õppurid:
    print(el.eesnimi, el.perenimi + ", isikukood:", el.isikukood)

  • 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