U kunt de betekenis van een operator in Python wijzigen, afhankelijk van de gebruikte operanden. In deze tutorial leer je hoe je operatoroverbelasting gebruikt in Python Object Oriented Programming.
Overbelasting door Python-operator
Python-operators werken voor ingebouwde klassen. Maar dezelfde operator gedraagt zich anders met verschillende typen. De +
operator voert bijvoorbeeld rekenkundige optellingen uit op twee getallen, voegt twee lijsten samen of voegt twee strings samen.
Deze functie in Python waarmee dezelfde operator een verschillende betekenis kan hebben volgens de context, wordt operatoroverbelasting 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 een punt in een 2D-coördinatensysteem probeert 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 (meest recente oproep laatste): Bestand "", regel 9, in print (p1 + p2) TypeError: niet-ondersteunde operand-type (s) voor +: 'Point' en 'Point'
Hier kunnen we zien dat a TypeError
werd verhoogd, aangezien Python niet wist hoe hij twee Point
objecten bij elkaar moest optellen .
We kunnen deze taak echter in Python bereiken door overbelasting van de operator. Maar laten we eerst eens kijken naar speciale functies.
Python speciale 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 dat we een nieuw object van die klasse maken, opgeroepen.
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)
Stel dat we willen dat de print()
functie de coördinaten van het Point
object afdrukt in plaats van wat we hebben. We kunnen een __str__()
methode in onze klasse definiëren 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()
functie 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) p1 = Point(2, 3) print(p1)
Uitvoer
(2, 3)
Dat is beter. Blijkt dat dezelfde methode wordt aangeroepen wanneer we de ingebouwde functie str()
of gebruiken format()
.
>>> str(p1) '(2,3)' >>> format(p1) '(2,3)'
Dus als je str(p1)
of gebruikt format(p1)
, roept Python intern de p1.__str__()
methode aan. Vandaar de naam, speciale functies.
Laten we nu teruggaan naar de overbelasting van de operator.
Overbelasting van de + Operator
Om de +
operator te overbelasten , moeten we de __add__()
functie in de klas implementeren . Met grote kracht komt een grote verantwoordelijkheid. Binnen deze functie kunnen we doen wat we willen. Maar het is verstandiger om een Point
object van de coördinatensom terug te geven.
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 gebruikt p1 + p2
, Python aanroept, p1.__add__(p2)
wat op zijn beurt is Point.__add__(p1,p2)
. Hierna wordt de additiebewerking uitgevoerd zoals we hebben gespecificeerd.
Evenzo kunnen we ook andere operators overbelasten. De speciale functie die we moeten implementeren, wordt hieronder weergegeven.
Operator | Uitdrukking | Intern |
---|---|---|
Toevoeging | p1 + p2 | p1.__add__(p2) |
Aftrekken | p1 - p2 | p1.__sub__(p2) |
Vermenigvuldiging | p1 * p2 | p1.__mul__(p2) |
Kracht | p1 ** p2 | p1.__pow__(p2) |
Divisie | p1 / p2 | p1.__truediv__(p2) |
Floor Divisie | p1 // p2 | p1.__floordiv__(p2) |
Rest (modulo) | p1 % p2 | p1.__mod__(p2) |
Bitsgewijs naar links verschuiven | p1 << p2 | p1.__lshift__(p2) |
Bitwise Right Shift | p1>> p2 | p1.__rshift__(p2) |
Bitwise EN | p1 & p2 | p1.__and__(p2) |
Bitsgewijs OF | p1 | p2 | p1.__or__(p2) |
Bitsgewijze XOR | p1 p2 | p1.__xor__(p2) |
Bitsgewijs NIET | ~p1 | p1.__invert__() |
Overbelastende vergelijkingsoperatoren
Python beperkt de overbelasting van operators niet tot alleen rekenkundige operators. We kunnen ook vergelijkingsoperatoren overbelasten.
Stel dat we het symbool voor minder dan <
symbool in onze Point
klas willen implementeren .
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
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)