Operaatori tähendust saate Pythonis muuta sõltuvalt kasutatavatest operandidest. Selles õpetuses saate teada, kuidas kasutada operaatori ülekoormamist Pythoni objektile orienteeritud programmeerimises.
Pythoni operaatori ülekoormus
Pythoni operaatorid töötavad sisseehitatud klassides. Kuid sama operaator käitub eri tüüpidega erinevalt. Näiteks teeb +
operaator kahele numbrile aritmeetilise liitmise, ühendab kaks loendit või liidab kaks stringi.
Seda Pythoni funktsiooni, mis võimaldab samal operaatoril vastavalt kontekstile erinevat tähendust nimetada operaatori ülekoormuseks.
Mis siis juhtub, kui kasutame neid kasutaja määratud klassi objektidega? Vaatleme järgmist klassi, mis püüab simuleerida punkti 2-D koordinaatide süsteemis.
class Point: def __init__(self, x=0, y=0): self.x = x self.y = y p1 = Point(1, 2) p2 = Point(2, 3) print(p1+p2)
Väljund
Traceback (viimane kõne viimati): fail "", rida 9, trükituna (p1 + p2) TypeError: +: 'Point' ja 'Point' ei toeta operanditüüpi (tüüpe)
Siin näeme, et TypeError
tõsteti a, kuna Python ei osanud kahte Point
objekti kokku liita.
Kuid selle ülesande saame Pythonis saavutada operaatori ülekoormuse kaudu. Kuid kõigepealt võtame ettekujutuse erifunktsioonidest.
Pythoni erifunktsioonid
Topeltkriipsuga algavaid klassi funktsioone __
nimetatakse Pythonis erifunktsioonideks.
Need funktsioonid pole tüüpilised funktsioonid, mille klassi jaoks määratleme. __init__()
Funktsiooni me eespool määratletud on üks neist. Seda nimetatakse iga kord, kui loome selle klassi uue objekti.
Pythonis on arvukalt muid erifunktsioone. Nende kohta lisateabe saamiseks külastage Pythoni erifunktsioone.
Spetsiaalsete funktsioonide abil saame oma klassi ühildada sisseehitatud funktsioonidega.
>>> p1 = Point(2,3) >>> print(p1)
Oletame, et soovime, et print()
funktsioon prindiks saadud koordinaadid Point
objekti asemel. Saame __str__()
oma klassis määratleda meetodi, mis kontrollib objekti printimist. Vaatame, kuidas seda saavutada:
class Point: def __init__(self, x = 0, y = 0): self.x = x self.y = y def __str__(self): return "((0),(1))".format(self.x,self.y)
Nüüd proovime print()
funktsiooni uuesti proovida .
class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return "((0), (1))".format(self.x, self.y) p1 = Point(2, 3) print(p1)
Väljund
(2, 3)
See on parem. Selgub, et seda sama meetodit kasutatakse siis, kui kasutame sisseehitatud funktsiooni str()
või format()
.
>>> str(p1) '(2,3)' >>> format(p1) '(2,3)'
Nii et kui kasutate str(p1)
või format(p1)
, kutsub Python p1.__str__()
meetodit sisemiselt . Siit ka nimi, erifunktsioonid.
Nüüd pöördume tagasi operaatori ülekoormuse juurde.
+ Operaatori ülekoormus
+
Operaatori ülekoormamiseks peame __add__()
klassis rakendama funktsiooni. Suure võimuga kaasneb suur vastutus. Selle funktsiooni sees võime teha kõike, mis meile meeldib. Kuid mõistlikum on tagastada Point
koordinaatide summa objekt.
class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return "((0),(1))".format(self.x, self.y) def __add__(self, other): x = self.x + other.x y = self.y + other.y return Point(x, y)
Proovime nüüd uuesti liitmistoimingut:
class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return "((0),(1))".format(self.x, self.y) def __add__(self, other): x = self.x + other.x y = self.y + other.y return Point(x, y) p1 = Point(1, 2) p2 = Point(2, 3) print(p1+p2)
Väljund
(3,5)
Tegelikult juhtub see, et kui kasutate p1 + p2
, helistab Python, p1.__add__(p2)
mis omakorda on Point.__add__(p1,p2)
. Pärast seda viiakse liitmistoiming läbi meie määratud viisil.
Samamoodi võime ka teisi operaatoreid üle koormata. Erifunktsioon, mille peame rakendama, on toodud allpool.
Operaator | Väljendus | Sisemiselt |
---|---|---|
Lisamine | p1 + p2 | p1.__add__(p2) |
Lahutamine | p1 - p2 | p1.__sub__(p2) |
Korrutamine | p1 * p2 | p1.__mul__(p2) |
Võimsus | p1 ** p2 | p1.__pow__(p2) |
Jaotus | p1 / p2 | p1.__truediv__(p2) |
Põrandadivisjon | p1 // p2 | p1.__floordiv__(p2) |
Ülejäänud (moodul) | p1 % p2 | p1.__mod__(p2) |
Nuppude kaupa vasakpoolne nihe | p1 << p2 | p1.__lshift__(p2) |
Parempoolne nihe paremale | p1>> p2 | p1.__rshift__(p2) |
Pikkade kaupa JA | p1 & p2 | p1.__and__(p2) |
Piki VÕI | p1 | p2 | p1.__or__(p2) |
Piki XOR | p1 p2 | p1.__xor__(p2) |
Bititi EI | ~p1 | p1.__invert__() |
Võrdlusoperaatorite ülekoormamine
Python ei piira operaatori ülekoormamist ainult aritmeetikaoperaatoritega. Võime koormata ka võrdlusoperaatoreid.
Oletame, et tahtsime <
oma Point
klassis rakendada sümbolist vähem kui sümbolit .
Võrdleme nende punktide suurust päritolust ja tagastame tulemuse sel eesmärgil. Seda saab rakendada järgmiselt.
# overloading the less than operator class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return "((0),(1))".format(self.x, self.y) def __lt__(self, other): self_mag = (self.x ** 2) + (self.y ** 2) other_mag = (other.x ** 2) + (other.y ** 2) return self_mag < other_mag p1 = Point(1,1) p2 = Point(-2,-3) p3 = Point(1,-1) # use less than print(p1
Output
True False False
Similarly, the special functions that we need to implement, to overload other comparison operators are tabulated below.
Operator Expression Internally
Less than p1 < p2
p1.__lt__(p2)
Less than or equal to p1 <= p2
p1.__le__(p2)
Equal to p1 == p2
p1.__eq__(p2)
Not equal to p1 != p2
p1.__ne__(p2)
Greater than p1> p2
p1.__gt__(p2)
Greater than or equal to p1>= p2
p1.__ge__(p2)