Du kan endre betydningen av en operatør i Python, avhengig av operandene som brukes. I denne opplæringen lærer du hvordan du bruker operatøroverbelastning i Python Object Oriented Programming.
Python-operatør Overbelastning
Python-operatører jobber for innebygde klasser. Men den samme operatøren oppfører seg annerledes med forskjellige typer. For eksempel vil +
operatøren utføre aritmetisk tillegg på to tall, slå sammen to lister eller sammenkoble to strenger.
Denne funksjonen i Python som lar den samme operatøren ha annen betydning i henhold til konteksten kalles operatøroverbelastning.
Så hva skjer når vi bruker dem med objekter i en brukerdefinert klasse? La oss se på følgende klasse, som prøver å simulere et punkt i 2-D koordinatsystem.
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)
Produksjon
Sporing (siste anrop sist): Fil "", linje 9, på trykk (p1 + p2) TypeError: ikke støttet operand type (r) for +: 'Point' og 'Point'
Her kan vi se at a TypeError
ble reist, siden Python ikke visste hvordan man skulle legge to Point
objekter sammen.
Imidlertid kan vi oppnå denne oppgaven i Python gjennom overbelastning av operatøren. Men først, la oss få en forestilling om spesialfunksjoner.
Python spesialfunksjoner
Klassefunksjoner som begynner med dobbelt understreking __
kalles spesialfunksjoner i Python.
Disse funksjonene er ikke de typiske funksjonene vi definerer for en klasse. Den __init__()
funksjonen vi definert ovenfor er en av dem. Det blir kalt hver gang vi lager et nytt objekt i den klassen.
Det er mange andre spesielle funksjoner i Python. Besøk Python Special Functions for å lære mer om dem.
Ved hjelp av spesialfunksjoner kan vi gjøre klassen vår kompatibel med innebygde funksjoner.
>>> p1 = Point(2,3) >>> print(p1)
Anta at vi vil at print()
funksjonen skal skrive ut koordinatene til Point
objektet i stedet for det vi fikk. Vi kan definere en __str__()
metode i klassen vår som styrer hvordan objektet blir skrevet ut. La oss se på hvordan vi kan oppnå dette:
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)
La oss nå prøve print()
funksjonen igjen.
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)
Produksjon
(2, 3)
Det er bedre. Det viser seg at denne samme metoden påkalles når vi bruker den innebygde funksjonen str()
eller format()
.
>>> str(p1) '(2,3)' >>> format(p1) '(2,3)'
Så når du bruker str(p1)
eller format(p1)
, kaller Python p1.__str__()
metoden internt . Derav navnet, spesielle funksjoner.
La oss nå gå tilbake til operatøroverbelastning.
Overbelastning av + operatøren
For å overbelaste +
operatøren, må vi implementere __add__()
funksjonen i klassen. Med stor makt kommer stort ansvar. Vi kan gjøre hva vi vil, inne i denne funksjonen. Men det er mer fornuftig å returnere et Point
objekt av koordinatsummen.
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)
La oss nå prøve tilleggsoperasjonen igjen:
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)
Produksjon
(3,5)
Det som faktisk skjer er at når du bruker p1 + p2
, ringer Python p1.__add__(p2)
som igjen er det Point.__add__(p1,p2)
. Etter dette utføres tilsetningsoperasjonen slik vi spesifiserte.
På samme måte kan vi også overbelaste andre operatører. Den spesielle funksjonen som vi trenger å implementere, er tabellert nedenfor.
Operatør | Uttrykk | Internt |
---|---|---|
Addisjon | p1 + p2 | p1.__add__(p2) |
Subtraksjon | p1 - p2 | p1.__sub__(p2) |
Multiplikasjon | p1 * p2 | p1.__mul__(p2) |
Makt | p1 ** p2 | p1.__pow__(p2) |
Inndeling | p1 / p2 | p1.__truediv__(p2) |
Etasjedivisjon | p1 // p2 | p1.__floordiv__(p2) |
Resten (modulo) | p1 % p2 | p1.__mod__(p2) |
Bitvis venstre skift | p1 << p2 | p1.__lshift__(p2) |
Bitvis høyre skift | p1>> p2 | p1.__rshift__(p2) |
Bitvis OG | p1 & p2 | p1.__and__(p2) |
Bitvis ELLER | p1 | p2 | p1.__or__(p2) |
Bitvis XOR | p1 p2 | p1.__xor__(p2) |
Bitvis IKKE | ~p1 | p1.__invert__() |
Overbelastning av sammenligningsoperatører
Python begrenser ikke operatørens overbelastning bare til aritmetiske operatører. Vi kan også overbelaste sammenligningsoperatører.
Anta at vi ønsket å implementere mindre enn symbol- <
symbolet i Point
klassen vår .
La oss sammenligne størrelsen på disse punktene fra opprinnelsen og returnere resultatet for dette formålet. Det kan implementeres som følger.
# 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)