11.5 Polimorfisms un dunder metodes
Stundas uzdevums: Izprast polimorfismu un Python speciālās ("dunder") metodes objektu pielāgošanai.
70 min plāns: Teorija un paraugs (~10 min) · 1. uzdevums (~15 min) - pārraksti vienu metodi vairākās klasēs · 2. uzdevums (~25 min) - izsauc tās vienā ciklā · 3. uzdevums (~20 min) - pievieno __str__ un __repr__. Papildu uzdevumu sāc tikai tad, ja pārējie trīs ir gatavi.
Pirms sāc: atver savas 11.4 stundas klases Dalibnieks, Kapteinis un Prezentetajs.
Teorija: Polimorfisms un dunder (__metode__)
Polimorfisms = daudzas formas. Dažādas klases ar to pašu metodes nosaukumu, bet atšķirīgu uzvedību.
class Dalibnieks:
def runa(self): print("Dalibnieks runā vispārīgi.")
class Prezentetajs(Dalibnieks):
def runa(self): print("Slaids ir gatavs, un neviens nepaniko!")
class Kapteinis(Dalibnieks):
def runa(self): print("Komanda gatava, marķieris atrasts!")
# Polimorfisms - vienots interfeiss, dažāda uzvedība
for v in [Dalibnieks(), Prezentetajs(), Kapteinis()]:
v.runa()
Dunder metodes (double underscore) ir iebūvētie āķi, kas ļauj klasei darboties ar Python operatoriem un funkcijām:
| Metode | Aktivizē |
|---|---|
__str__ | str(o) un print(o) |
__repr__ | repr(o), REPL izvade |
__eq__ | o1 == o2 |
__lt__, __gt__ | <, > (sortēšana) |
__add__ | o1 + o2 |
__len__ | len(o) |
__contains__ | x in o |
Praktiskie uzdevumi
1. uzdevums -
Pārraksti vienu metodi vairākās klasēs
Beigās vienam metodes nosaukumam būs trīs dažādas uzvedības.
- Pievieno klasei
Dalibnieksmetodidef runa(self):ar vispārīgu tekstu. - Pievieno klasei
Kapteinistādu pašu metodi ar citu tekstu. - Pievieno klasei
Prezentetajsvēl vienu variantu. - Izveido pa vienam objektam no katras klases.
- Izsauc katram
runa()atsevišķi. - Pieraksti, kura klase noteica, kurš teksts izdrukājās.
Gatavs, kad: viens metodes nosaukums dod trīs dažādas izvades atkarībā no objekta klases.
2. uzdevums -
Izsauc tās vienā ciklā
Beigās viens cikls apkalpos jebkuru lomu skaitu.
- Izveido sarakstu ar visiem trim objektiem.
- Uzraksti ciklu
for d in dalibnieki:. - Izsauc ciklā
d.runa(). - Palaid un pārbaudi, ka izdrukājas trīs dažādi teksti.
- Pievieno sarakstam vēl vienu jaunu lomu.
- Palaid vēlreiz un pārbaudi, vai cikls bija jāmaina.
- Pieraksti vienu secinājumu: kāpēc te nevajag
ifpēc klases nosaukuma.
Gatavs, kad: pievienojot ceturto lomu, cikls strādā bez izmaiņām.
3. uzdevums -
Pievieno __str__ un __repr__
Beigās objekts pats zinās, kā izskatīties izdrukā.
- Izdrukā objektu bez papildu metodēm un pieraksti rezultātu.
- Pievieno klasei
def __str__(self):, kas atgriež vārdu un enerģiju. - Izdrukā objektu vēlreiz un salīdzini.
- Pievieno
def __repr__(self):ar tehnisku pierakstu. - Izdrukā sarakstu ar objektiem un pieraksti, kura metode nostrādāja.
- Pieraksti, kur lieto
__str__un kur__repr__. - Pārbaudi, ka
print(objekts)unprint([objekts])dod dažādu rezultātu.
Gatavs, kad: atsevišķi izdrukāts objekts rāda __str__, bet sarakstā - __repr__.
Papildu uzdevums - Pievieno salīdzināšanu
Ja pamatdarbs ir gatavs, ļauj kārtot dalībniekus pēc enerģijas.
- Pievieno klasei
def __lt__(self, cits):. - Atgriez tajā
return self.energija < cits.energija. - Izsauc
sorted(dalibnieki). - Izdrukā sakārtoto sarakstu.
- Pieraksti, kāpēc bez
__lt__kārtošana neizdevās.
Gatavs, kad: sorted() sakārto dalībniekus pēc enerģijas, nevis met TypeError.
Biežākās kļūdas
- __str__ atgriež ne-string: Vienmēr atgriež
str, citādiTypeError. - __eq__ bez __hash__: Ja klase salīdzināma, bet maināma - definē
__hash__ = None. - Aizmirsts atgriezt vērtību:
__lt__,__eq__- vienmērreturn True/False.
Koda piemērs
class Dalibnieks:
def __init__(self, vards, energija): self.vards = vards; self.energija = energija
def __str__(self): return f"{self.vards} ({self.energija} enerģija)"
def __repr__(self): return f"Dalibnieks({self.vards!r}, energija={self.energija})"
def __lt__(self, other): return self.energija < other.energija
def __eq__(self, other): return self.energija == other.energija
dalibnieki = [Dalibnieks("Anna", 100), Dalibnieks("Jānis", 80), Dalibnieks("Eva", 120)]
for v in sorted(dalibnieki):
print(v)
Anna (100 enerģija)
Eva (120 enerģija)