Preopterećenje operatora Pythona

Značenje operatora u Pythonu možete promijeniti ovisno o korištenim operandima. U ovom vodiču naučit ćete kako koristiti preopterećenje operatora u Python objektno orijentiranom programiranju.

Preopterećenje operatora Pythona

Python operateri rade za ugrađene klase. Ali isti se operator različito ponaša s različitim vrstama. Na primjer, +operator će izvršiti aritmetičko sabiranje dva broja, spojiti dva popisa ili spojiti dva niza.

Ova značajka u Pythonu koja omogućava istom operatoru da ima različita značenja u skladu s kontekstom naziva se preopterećenje operatora.

Pa što se događa kada ih koristimo s objektima korisnički definirane klase? Razmotrimo sljedeću klasu koja pokušava simulirati točku u 2-D koordinatnom sustavu.

 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)

Izlaz

 Traceback (najnoviji zadnji poziv): Datoteka "", red 9, u ispisu (p1 + p2) TypeError: nepodržani tip (ovi) operanda za +: 'Point' i 'Point'

Ovdje možemo vidjeti da TypeErrorje postavljeno a, jer Python nije znao dodati dva Pointobjekta zajedno.

Međutim, ovaj zadatak u Pythonu možemo postići preopterećenjem operatora. Ali prvo, steknimo pojam o posebnim funkcijama.

Python posebne funkcije

Funkcije klase koje počinju dvostrukim donjim crtama __nazivaju se posebnim funkcijama u Pythonu.

Te funkcije nisu tipične funkcije koje definiramo za klasu. __init__()Funkcija mi je gore definirano je jedan od njih. Pozva se svaki put kada stvorimo novi objekt te klase.

U Pythonu postoje brojne druge posebne funkcije. Posjetite Python Special Functions da biste saznali više o njima.

Korištenjem posebnih funkcija našu klasu možemo učiniti kompatibilnom s ugrađenim funkcijama.

 >>> p1 = Point(2,3) >>> print(p1) 

Pretpostavimo da želimo da print()funkcija ispisuje koordinate Pointobjekta umjesto onoga što smo dobili. U __str__()našoj klasi možemo definirati metodu koja kontrolira način ispisa predmeta. Pogledajmo kako to možemo postići:

 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)

Pokušajmo print()ponovo s funkcijom.

 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)

Izlaz

 (2, 3)

Tako je bolje. Ispada, da se ta ista metoda poziva kada koristimo ugrađenu funkciju str()ili format().

 >>> str(p1) '(2,3)' >>> format(p1) '(2,3)'

Dakle, kada koristite str(p1)ili format(p1), Python interno poziva p1.__str__()metodu. Otuda i naziv, posebne funkcije.

Vratimo se sada preopterećenju operatera.

Preopterećenje operatora +

Da bismo preopteretili +operator, morat ćemo implementirati __add__()funkciju u klasu. S velikom moći dolazi velika odgovornost. Unutar ove funkcije možemo raditi što god želimo. Ali razumnije je vratiti Pointobjekt koordinatnog zbroja.

 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)

Pokušajmo ponovo s operacijom zbrajanja:

 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)

Izlaz

 (3,5)

Ono što se zapravo događa je da, kada koristite p1 + p2, Python poziva p1.__add__(p2)što pak jest Point.__add__(p1,p2). Nakon toga, operacija zbrajanja izvodi se na način koji smo odredili.

Slično tome, možemo preopteretiti i druge operatore. Posebna funkcija koju trebamo implementirati prikazana je u nastavku.

Operater Izraz Interno
Dodatak p1 + p2 p1.__add__(p2)
Oduzimanje p1 - p2 p1.__sub__(p2)
Množenje p1 * p2 p1.__mul__(p2)
Vlast p1 ** p2 p1.__pow__(p2)
Podjela p1 / p2 p1.__truediv__(p2)
Podna podjela p1 // p2 p1.__floordiv__(p2)
Ostatak (po modulu) p1 % p2 p1.__mod__(p2)
Pomicanje ulijevo ulijevo p1 << p2 p1.__lshift__(p2)
Pomicanje udesno udesno p1>> p2 p1.__rshift__(p2)
Bitno I p1 & p2 p1.__and__(p2)
Bitno ILI p1 | p2 p1.__or__(p2)
Bitno XOR p1 p2 p1.__xor__(p2)
Bitno NE ~p1 p1.__invert__()

Preopterećenje operatora usporedbe

Python ne ograničava preopterećenje operatora samo na aritmetičke operatore. Možemo preopteretiti i operatore usporedbe.

Pretpostavimo da smo željeli implementirati simbol manji od <simbola u našu Pointklasu.

Usporedimo veličinu tih točaka iz ishodišta i vratimo rezultat u tu svrhu. Može se provesti na sljedeći način.

 # 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)

Zanimljivi članci...