OOP: spetsiaalsed meetodid

Pythoni klass võib spetsiaalsete meetoditega implementeerida operatsioone nagu erinevad aritmeetilise tehted objektide vahel, objekti initsialiseerimine ja palju muud. See on Pythoni viis operaatoreid üle laadida, et defineerida vajalikku käitumist objektide vahel.

Vaatame kõige populaarsemaid spetsiaalseid meetodeid.

__init__

Klassi initsialiseerimismeetod ehk konstruktor. Objekti loomisel jõuavad argumendid sellesse meetodisse. See on hea koht objekti muutujate salvestamiseks.

class Dog:

    def __init__(self, name):
        self.name = name

__str__

Seda meetodit kutsub str(object) ehk see on objekti ilus sõneline representatsioon. Kui meil see puudub, siis vaikimisi olemasolev objekti sõne väljaprint pole väga informatiivne.

class Dog:

    def __init__(self, name):
        self.name = name

d = Dog('Leo')
print(d)  # <__main__.Dog object at 0x101d665c0>


# Now let's add the __str__ method
class Dog:

    def __init__(self, name):
        self.name = name

    def __str__(self):
        return self.name


d = Dog('Leo')
print(d)  # Leo

__repr__

Seda meetodit kutsub repr(object). See annab sarnaselt __str__ meetodile objekti representatsiooni, aga see on mõeldud rohkem masinloetavuseks. Kui printida listi objektidest, siis listi enda __str__ kutsub iga listi objekti __repr__ meetodit. Hea stackoverflow postitus erinevustset: https://stackoverflow.com/questions/1436703/difference-between-str-and-repr

Objektide võrdluseks on meetodid __eq__, __ne__, __lt__, __gt__, __le__, __ge__. Vaatame näidet, kus kirjutatakse üle võrdluse meetodid kaartide vahel. Kui on üks baas võrdluse meetod üle kirjutatud, siis saavad teised seda ära kasutada. Võrdlusmeetodite ülekirjutamine võimaldab näiteks kaarte sorteerida.

class Card:

    def __init__(self, suit, rank):
        self.suit = suit
        self.rank = rank

    def __str__(self):
        return f'{self.rank} of {self.suit}'

    def __repr__(self):
        return self.__str__()

    def __eq__(self, other):
        return self.suit == other.suit and self.rank == other.rank

    def __gt__(self, other):
        if self.suit == other.suit:
            return self.rank > other.rank
        return self.suit > other.suit

    def __ne__(self, other):
        return not self == other

    def __le__(self, other):
        return not self > other

    def __lt__(self, other):
        return not (self > other or self == other)

    def __ge__(self, other):
        return not self < other


cards = [
    Card('Spades', 7),
    Card('Hearts', 9),
    Card('Spades', 8),
    Card('Hearts', 7),
    Card('Spades', 6),
]

print(sorted(cards))
# [7 of Hearts, 9 of Hearts, 6 of Spades, 7 of Spades, 8 of Spades]
print(sorted(cards, reverse=True))
# [8 of Spades, 7 of Spades, 6 of Spades, 9 of Hearts, 7 of Hearts]

Lisaks on palju erinevate konteineritega seotud meetodeid __len__, __getitem__, __setitem__, __delitem__, __iter__, __reversed__, __contains__, __missing__.

Nõuanne

Vaata põhjaliku nimekirja meetoditest koos lühikirjeldustega https://rszalski.github.io/magicmethods/

Näiteks __missing__ meetodit saab kasutada sõnastiku alamklassides ja seda kutsutakse juhul, kui üritatakse sõnastikust võtta elementi võtmega, mida pole.

Lihtne näide, kus oma loodud sõnastik tagastab puuduva võtme korral None ega viska erindit KeyError.

class MyDict(dict):

    def __missing__(self, key):
        return None


d = MyDict()
d['age'] = 5
print(d['name'])  # None'

Rohkem lugemist

Põhjalik nimekiri näidete ja selgitusega: https://rszalski.github.io/magicmethods/

Ametlik dokumentatsioon: https://docs.python.org/3/reference/datamodel.html#special-method-names