ebSkola

11.2 Konstruktori un atribūti

Stundas uzdevums: Iemācīties pareizi inicializēt objektus, izmantojot __init__ metodi un noklusējuma argumentus.

SR 2.4.18. Lieto OOP pamatus SR 2.4.15. Modulāras programmas un funkcijas

70 min plāns: Teorija un paraugs (~10 min) · 1. uzdevums (~15 min) - pārraksti klasi ar __init__ · 2. uzdevums (~25 min) - pievieno noklusējuma vērtības · 3. uzdevums (~20 min) - pārbaudi datus konstruktorā. Papildu uzdevumu sāc tikai tad, ja pārējie trīs ir gatavi.

Pirms sāc: atver savu 11.1 stundas failu klases.py. Šoreiz atbrīvosies no atribūtu piešķiršanas ar roku.

Teorija: __init__ - objekta dzimšana

Manuāli iestatīt katra objekta atribūtus ir kļūdu pilna pieeja. __init__ ir konstruktors - speciāla metode, ko Python automātiski izsauc, kad veido jaunu objektu.

class Dalibnieks:
    def __init__(self, vards, energija=100, klase="kapteinis"):
        # self ir norāde uz JAUNO objektu
        self.vards = vards
        self.energija = energija
        self.maks_energija = energija
        self.klase = klase
        self.aktiva = True

    def info(self):
        return f"{self.vards} ({self.klase}): {self.energija}/{self.maks_energija} enerģija"

# Izveide ar pozicionāliem argumentiem
v1 = Dalibnieks("Marta")
# Izveide ar nosauktiem argumentiem
v2 = Dalibnieks(vards="Jānis", energija=80, klase="prezentetajs")

print(v1.info())  # Marta (kapteinis): 100/100 enerģija
print(v2.info())  # Jānis (prezentetajs): 80/80 enerģija

Atribūtu tipi:

  • Objekta atribūti (self.x) - katram objektam savs.
  • Klases atribūti (definēti klases ķermenī ārpus metodēm) - kopīgi visiem objektiem.
  • Privātie atribūti (sākas ar _) - paredzēti tikai iekšējai lietošanai.

Praktiskie uzdevumi

1. uzdevums -

Pārraksti klasi ar __init__

Beigās objekta izveide un datu piešķiršana notiks vienā rindā.

  1. Ieraksti klasē def __init__(self, vards, energija):.
  2. Piešķir tajā self.vards = vards.
  3. Piešķir arī self.energija = energija.
  4. Izveido objektu ar Dalibnieks("Anna", 100).
  5. Izdrukā objekta vārdu un enerģiju.
  6. Mēģini izveidot objektu bez argumentiem un izlasi kļūdu.

Gatavs, kad: objektu var izveidot vienā rindā, bet bez argumentiem rodas TypeError.

2. uzdevums -

Pievieno noklusējuma vērtības

Beigās daļu argumentu varēs izlaist.

  1. Nomaini parametru uz energija=100.
  2. Pievieno trešo parametru klase="kapteinis".
  3. Izveido objektu tikai ar vārdu.
  4. Izdrukā visus trīs atribūtus.
  5. Izveido otru objektu, norādot arī klasi.
  6. Pievieno self.maks_energija = energija un paskaidro sev, kāpēc tas noder.

Gatavs, kad: objektu var izveidot gan ar vienu argumentu, gan ar trim, un abos gadījumos tas strādā.

3. uzdevums -

Pārbaudi datus konstruktorā

Beigās klase pati neļaus izveidot bezjēdzīgu objektu.

  1. Pievieno if energija <= 0: un zem tā raise ValueError("Enerģijai jābūt pozitīvai").
  2. Pievieno pārbaudi arī tukšam vārdam.
  3. Mēģini izveidot objektu ar enerģiju -5.
  4. Izlasi kļūdas tekstu un pārbaudi, ka tas ir tavs.
  5. Mēģini izveidot objektu ar tukšu vārdu.
  6. Izveido derīgu objektu un pārliecinies, ka tas izdodas.
  7. Pieraksti vienu secinājumu: kāpēc pārbaudi labāk likt konstruktorā, nevis katrā metodē.

Gatavs, kad: nederīgi dati met tavu ValueError ar saprotamu tekstu, bet derīgs objekts izveidojas.

Papildu uzdevums - Pievieno izveides laiku

Ja pamatdarbs ir gatavs, liec objektam atcerēties, kad tas radīts.

  1. Importē from datetime import datetime.
  2. Pievieno konstruktorā self.izveidots = datetime.now().
  3. Izveido divus objektus ar nelielu pauzi starp tiem.
  4. Izdrukā abu izveides laikus.
  5. Pieraksti, kāpēc šo vērtību nevajag padot kā argumentu.

Gatavs, kad: abiem objektiem ir atšķirīgs izveides laiks, ko tu nekur neievadīji.

Biežākās kļūdas

  • Aizmirsts self konstruktora pirmajā argumentā: __init__(self, ...) - vienmēr.
  • Maināmi klases atribūti: klase_atrib = [] tiek dalīts starp objektiem!
  • __init__ atgriež None: Nelieto return self - tas nav pareizi.

Koda piemērs

class Dalibnieks:
    def __init__(self, vards, energija=100, klase="kapteinis"):
        if energija <= 0:
            raise ValueError("Enerģijai jābūt pozitīvai")
        if not vards:
            raise ValueError("Vārds nedrīkst būt tukšs")
        self.vards = vards
        self.energija = energija
        self.maks_energija = energija
        self.klase = klase

v1 = Dalibnieks("Marta")
v2 = Dalibnieks(vards="Jānis", energija=80, klase="prezentetajs")
print(f"{v1.vards}: {v1.energija}/{v1.maks_energija}")
print(f"{v2.vards} ({v2.klase}): {v2.energija}/{v2.maks_energija}")
Marta: 100/100
Jānis (prezentetajs): 80/80