Du kan ændre betydningen af en operator i Python afhængigt af de anvendte operander. I denne vejledning lærer du, hvordan du bruger overbelastning af operatører i Python Object Oriented Programming.
Python Operator Overbelastning
Python-operatører arbejder for indbyggede klasser. Men den samme operatør opfører sig forskelligt med forskellige typer. For eksempel vil +
operatøren udføre aritmetisk tilføjelse på to tal, flette to lister eller sammenkæde to strenge.
Denne funktion i Python, der gør det muligt for den samme operatør at have forskellig betydning i henhold til konteksten kaldes operatøroverbelastning.
Så hvad sker der, når vi bruger dem med objekter i en brugerdefineret klasse? Lad os overveje følgende klasse, der forsøger at 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)
Produktion
Traceback (seneste opkald sidst): Fil "", linje 9, i tryk (p1 + p2) TypeError: ikke-understøttet operand-type (r) for +: 'Point' og 'Point'
Her kan vi se, at a TypeError
blev rejst, da Python ikke vidste, hvordan man tilføjede to Point
objekter sammen.
Vi kan dog opnå denne opgave i Python gennem operatøroverbelastning. Men lad os først få et indtryk af specielle funktioner.
Python-specialfunktioner
Klassefunktioner, der begynder med dobbelt understregning __
, kaldes specielle funktioner i Python.
Disse funktioner er ikke de typiske funktioner, som vi definerer for en klasse. Den __init__()
funktion vi defineret ovenfor er en af dem. Det kaldes hver gang vi opretter et nyt objekt i den klasse.
Der er mange andre specielle funktioner i Python. Besøg Python Special Funktioner for at lære mere om dem.
Ved hjælp af specielle funktioner kan vi gøre vores klasse kompatibel med indbyggede funktioner.
>>> p1 = Point(2,3) >>> print(p1)
Antag, at vi vil have print()
funktionen til at udskrive Point
objektets koordinater i stedet for det, vi fik. Vi kan definere en __str__()
metode i vores klasse, der styrer, hvordan objektet bliver udskrevet. Lad os se på, hvordan vi kan opnå 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)
Lad os nu prøve print()
funktionen igen.
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)
Produktion
(2, 3)
Det er bedre. Det viser sig, at den samme metode påberåbes, når vi bruger den indbyggede funktion str()
eller format()
.
>>> str(p1) '(2,3)' >>> format(p1) '(2,3)'
Så når du bruger str(p1)
eller format(p1)
, kalder Python internt p1.__str__()
metoden. Deraf navnet, specielle funktioner.
Lad os nu gå tilbage til operatøroverbelastning.
Overbelastning af + operatøren
For at overbelaste +
operatøren skal vi implementere __add__()
funktionen i klassen. Med store magtbeføjelser følger store forpligtigelser. Vi kan gøre hvad vi vil inden i denne funktion. Men det er mere fornuftigt at returnere et Point
objekt af 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)
Lad os nu prøve tilføjelsesoperationen igen:
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)
Produktion
(3,5)
Hvad der faktisk sker er, at når du bruger p1 + p2
, kalder Python, p1.__add__(p2)
hvilket igen er Point.__add__(p1,p2)
. Efter dette udføres tilføjelsesoperationen som vi specificerede.
På samme måde kan vi også overbelaste andre operatører. Den særlige funktion, som vi har brug for at implementere, er vist i nedenstående tabel.
Operatør | Udtryk | Internt |
---|---|---|
Tilføjelse | p1 + p2 | p1.__add__(p2) |
Subtraktion | p1 - p2 | p1.__sub__(p2) |
Multiplikation | p1 * p2 | p1.__mul__(p2) |
Strøm | p1 ** p2 | p1.__pow__(p2) |
Division | p1 / p2 | p1.__truediv__(p2) |
Floor Division | p1 // p2 | p1.__floordiv__(p2) |
Resten (modulo) | p1 % p2 | p1.__mod__(p2) |
Bitvis venstre skift | p1 << p2 | p1.__lshift__(p2) |
Bitvis højre 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 af sammenligningsoperatører
Python begrænser ikke overbelastning af operatører til kun aritmetiske operatører. Vi kan også overbelaste sammenligningsoperatører.
Antag, at vi ville implementere mindre end <
symbolsymbolet i vores Point
klasse.
Lad os sammenligne størrelsen af disse punkter fra oprindelsen og returnere resultatet til dette formål. 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)