Overbelasting van Python-operator
Overbelasting Python-operator
Je kunt de betekenis van een operator in Python veranderen, afhankelijk van de gebruikte operanden. In deze tutorial leer je hoe je operator-overloading kunt gebruiken in Python Object Oriented Programming.
Python-operator overbelast
Python-operators werken voor ingebouwde klassen. Maar dezelfde operator gedraagt zich anders bij verschillende typen. Bijvoorbeeld de +
operator voert rekenkundige optellingen uit op twee getallen, voegt twee lijsten samen of voegt twee strings samen.
Deze functie in Python die het mogelijk maakt dat dezelfde operator een verschillende betekenis heeft afhankelijk van de context, wordt overbelasting van de operator genoemd.
Dus wat gebeurt er als we ze gebruiken met objecten van een door de gebruiker gedefinieerde klasse? Laten we eens kijken naar de volgende klasse, die probeert een punt in een 2D-coördinatensysteem te simuleren.
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)
Uitvoer
Traceback (most recent call last): File "<string>", line 9, in <module> print(p1+p2) TypeError: unsupported operand type(s) for +: 'Point' and 'Point'
Hier kunnen we zien dat een TypeError
werd opgevoed, omdat Python niet wist hoe hij twee Point
. moest toevoegen objecten samen.
We kunnen deze taak echter in Python bereiken door overbelasting van de operator. Maar laten we eerst een idee krijgen over speciale functies.
Speciale Python-functies
Klassefuncties die beginnen met een dubbel onderstrepingsteken __
worden in Python speciale functies genoemd.
Deze functies zijn niet de typische functies die we voor een klasse definiëren. De __init__()
functie die we hierboven hebben gedefinieerd, is er een van. Het wordt elke keer aangeroepen als we een nieuw object van die klasse maken.
Er zijn tal van andere speciale functies in Python. Bezoek Python Special Functions om er meer over te leren.
Met behulp van speciale functies kunnen we onze klas compatibel maken met ingebouwde functies.
>>> p1 = Point(2,3)
>>> print(p1)
<__main__.Point object at 0x00000000031F8CC0>
Stel dat we de print()
. willen functie om de coördinaten van de Point
. af te drukken object in plaats van wat we hebben. We kunnen een __str__()
. definiëren methode in onze klasse die bepaalt hoe het object wordt afgedrukt. Laten we eens kijken hoe we dit kunnen bereiken:
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)
Laten we nu de print()
. proberen functie weer.
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)
Uitvoer
(2, 3)
Dat is beter. Blijkt dat dezelfde methode wordt aangeroepen wanneer we de ingebouwde functie str()
gebruiken of format()
.
>>> str(p1)
'(2,3)'
>>> format(p1)
'(2,3)'
Dus, wanneer u str(p1)
. gebruikt of format(p1)
, Python roept intern de p1.__str__()
. aan methode. Vandaar de naam, speciale functies.
Laten we nu teruggaan naar overbelasting van de operator.
De + Operator overbelasten
Om de +
te overbelasten operator, moeten we __add__()
. implementeren functioneren in de klas. Met grote macht komt grote verantwoordelijkheid. Binnen deze functie kunnen we doen wat we willen. Maar het is verstandiger om een Point
. terug te sturen object van de coördinatensom.
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)
Laten we nu de optelbewerking opnieuw proberen:
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)
Uitvoer
(3,5)
Wat er feitelijk gebeurt, is dat wanneer u p1 + p2
. gebruikt , Python roept p1.__add__(p2)
aan wat op zijn beurt Point.__add__(p1,p2)
. is . Hierna wordt de optelbewerking uitgevoerd zoals we hebben gespecificeerd.
Op dezelfde manier kunnen we ook andere operators overbelasten. De speciale functie die we moeten implementeren is hieronder weergegeven.
Operator | Uitdrukking | Intern |
---|---|---|
Toevoeging | p1 + p2 | p1.__add__(p2) |
Aftrekken | p1 - p2 | p1.__sub__(p2) |
Vermenigvuldigen | p1 * p2 | p1.__mul__(p2) |
Kracht | p1 ** p2 | p1.__pow__(p2) |
Divisie | p1 / p2 | p1.__truediv__(p2) |
Verdieping | p1 // p2 | p1.__floordiv__(p2) |
Overige (modulo) | p1 % p2 | p1.__mod__(p2) |
Bitsgewijze verschuiving naar links | p1 << p2 | p1.__lshift__(p2) |
Bitsgewijze verschuiving naar rechts | p1 >> p2 | p1.__rshift__(p2) |
Bitgewijs EN | p1 & p2 | p1.__and__(p2) |
Bitgewijs OF | p1 | p2 | p1.__or__(p2) |
Bitwise XOR | p1 ^ p2 | p1.__xor__(p2) |
Bitgewijs NIET | ~p1 | p1.__invert__() |
Overbelastingsvergelijkingsoperators
Python beperkt de overbelasting van operators niet alleen tot rekenkundige operators. We kunnen vergelijkingsoperators ook overbelasten.
Stel dat we het kleiner dan-symbool <
. willen implementeren symbool in onze Point
klasse.
Laten we de grootte van deze punten vanaf de oorsprong vergelijken en het resultaat voor dit doel retourneren. Het kan als volgt worden geïmplementeerd.
# 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<p2)
print(p2<p3)
print(p1<p3)
Uitvoer
True False False
Evenzo worden de speciale functies die we moeten implementeren om andere vergelijkingsoperatoren te overbelasten hieronder weergegeven.
Operator | Uitdrukking | Intern |
---|---|---|
Minder dan | p1 < p2 | p1.__lt__(p2) |
Kleiner dan of gelijk aan | p1 <= p2 | p1.__le__(p2) |
Gelijk aan | p1 == p2 | p1.__eq__(p2) |
Niet gelijk aan | p1 != p2 | p1.__ne__(p2) |
Groter dan | p1 > p2 | p1.__gt__(p2) |
Groter dan of gelijk aan | p1 >= p2 | p1.__ge__(p2) |
Python