Supraîncărcarea operatorului Python

Puteți schimba semnificația unui operator în Python în funcție de operanzii utilizați. În acest tutorial, veți învăța cum să utilizați supraîncărcarea operatorului în programarea orientată pe obiecte Python.

Supraîncărcarea operatorului Python

Operatorii Python lucrează pentru clase încorporate. Dar același operator se comportă diferit cu diferite tipuri. De exemplu, +operatorul va efectua adunarea aritmetică pe două numere, va îmbina două liste sau va concatena două șiruri.

Această caracteristică din Python care permite aceluiași operator să aibă o semnificație diferită în funcție de context se numește supraîncărcare a operatorului.

Ce se întâmplă atunci când le folosim cu obiecte dintr-o clasă definită de utilizator? Să luăm în considerare următoarea clasă, care încearcă să simuleze un punct în sistemul de coordonate 2-D.

 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)

Ieșire

 Traceback (ultimul apel cel mai recent): Fișier "", linia 9, tipărit (p1 + p2) TypeError: tipuri de operand neacceptate pentru +: „Punct” și „Punct”

Aici, putem vedea că a a TypeErrorfost ridicat, deoarece Python nu știa cum să adauge două Pointobiecte împreună.

Cu toate acestea, putem realiza această sarcină în Python prin supraîncărcarea operatorului. Dar mai întâi, să obținem o noțiune despre funcțiile speciale.

Funcții speciale Python

Funcțiile de clasă care încep cu subliniere dublă __sunt numite funcții speciale în Python.

Aceste funcții nu sunt funcțiile tipice pe care le definim pentru o clasă. __init__()Functia am definit mai sus este una dintre ele. Este apelat de fiecare dată când creăm un obiect nou din clasa respectivă.

Există multe alte funcții speciale în Python. Accesați funcțiile speciale Python pentru a afla mai multe despre ele.

Folosind funcții speciale, putem face clasa noastră compatibilă cu funcțiile încorporate.

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

Să presupunem că vrem ca print()funcția să imprime coordonatele Pointobiectului în loc de ceea ce am obținut. Putem defini o __str__()metodă din clasa noastră care controlează modul în care obiectul este tipărit. Să vedem cum putem realiza acest lucru:

 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)

Acum să încercăm din print()nou funcția.

 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)

Ieșire

 (2, 3)

Asa e mai bine. Se pare că aceeași metodă este invocată atunci când folosim funcția încorporată str()sau format().

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

Deci, când utilizați str(p1)sau format(p1), Python apelează intern p1.__str__()metoda. De aici și numele, funcțiile speciale.

Acum să revenim la supraîncărcarea operatorului.

Supraîncărcarea operatorului +

Pentru a supraîncărca +operatorul, va trebui să implementăm __add__()funcția din clasă. Cu o mare putere vine o mare responsabilitate. Putem face orice ne place, în interiorul acestei funcții. Dar este mai sensibil să returnăm un Pointobiect din suma coordonatelor.

 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)

Acum să încercăm din nou operația de adăugare:

 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)

Ieșire

 (3,5)

Ceea ce se întâmplă de fapt este că, atunci când utilizați p1 + p2, apelurile Python p1.__add__(p2)care la rândul lor sunt Point.__add__(p1,p2). După aceasta, operația de adăugare se efectuează așa cum am specificat.

În mod similar, putem supraîncărca și alți operatori. Funcția specială pe care trebuie să o implementăm este prezentată mai jos.

Operator Expresie Intern
Plus p1 + p2 p1.__add__(p2)
Scădere p1 - p2 p1.__sub__(p2)
Multiplicare p1 * p2 p1.__mul__(p2)
Putere p1 ** p2 p1.__pow__(p2)
Divizia p1 / p2 p1.__truediv__(p2)
Divizia etajului p1 // p2 p1.__floordiv__(p2)
Rămășiță (modulo) p1 % p2 p1.__mod__(p2)
Shift stânga bit p1 << p2 p1.__lshift__(p2)
Shift în dreapta bit p1>> p2 p1.__rshift__(p2)
Bitwise ȘI p1 & p2 p1.__and__(p2)
OR bit p1 | p2 p1.__or__(p2)
Bitwise XOR p1 p2 p1.__xor__(p2)
Bitwise NU ~p1 p1.__invert__()

Operatori comparativi de supraîncărcare

Python nu limitează supraîncărcarea operatorului doar la operatorii aritmetici. Putem supraîncărca și operatorii de comparație.

Să presupunem că am vrut să implementăm simbolul mai mic decât <simbolul din Pointclasa noastră .

Let us compare the magnitude of these points from the origin and return the result for this purpose. It can be implemented as follows.

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

Articole interesante...