Az operandusok függvényében megváltoztathatja az operátor jelentését a Pythonban. Ebben az oktatóanyagban megtudhatja, hogyan kell használni az operátorok túlterhelését a Python objektumorientált programozásban.
Python Operator túlterhelés
A Python operátorok beépített osztályoknál dolgoznak. De ugyanaz a kezelő másképp viselkedik a különböző típusokkal. Például az +
operátor két számon elvégzi a számtani összeadást, két listát egyesít vagy két karakterláncot összefűz.
Ezt a szolgáltatást a Pythonban, amely lehetővé teszi, hogy ugyanazon operátor a kontextustól függően eltérő jelentéssel bírjon, operátor túlterhelésnek nevezzük.
Tehát mi történik, ha egy felhasználó által definiált osztály objektumaival használjuk őket? Vizsgáljuk meg a következő osztályt, amely megpróbál szimulálni egy pontot a 2-D koordinátarendszerben.
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)
Kimenet
Traceback (a legutóbbi hívás utoljára): "" fájl, 9. sor nyomtatásban (p1 + p2) TypeError: nem támogatott operandus típus (ok) a + -hoz: "Pont" és "Pont"
Itt láthatjuk, hogy a TypeError
felvetődött, mivel a Python nem tudta, hogyan adjon hozzá két Point
objektumot.
Ezt a feladatot azonban elérhetjük a Pythonban az operátor túlterhelésével. De először vegyünk egy képet a speciális funkciókról.
Python speciális funkciók
A kettős aláhúzással kezdődő osztályfüggvényeket __
speciális függvényeknek nevezzük a Pythonban.
Ezek a függvények nem azok a tipikus funkciók, amelyeket egy osztályhoz definiálunk. Az a __init__()
funkció, amelyet fentebb definiáltunk, az egyik. Minden alkalommal hívják, amikor létrehozunk egy új objektumot az osztályból.
A Pythonban számos egyéb speciális funkció található. Látogassa meg a Python Special Functions funkciót, hogy többet tudjon meg róluk.
Speciális funkciókkal kompatibilisvé tehetjük osztályunkat a beépített funkciókkal.
>>> p1 = Point(2,3) >>> print(p1)
Tegyük fel, hogy azt akarjuk, hogy a print()
függvény kinyomtassa az Point
objektum koordinátáit, nem pedig azt, amit kaptunk. Osztályunkban meghatározhatunk egy __str__()
módszert, amely szabályozza az objektum nyomtatásának módját. Nézzük meg, hogyan érhetjük el ezt:
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)
Most próbáljuk meg print()
újra a funkciót.
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)
Kimenet
(2, 3)
Ez jobb. Kiderült, hogy ez ugyanaz a módszer akkor aktiválódik, ha használjuk a beépített függvény str()
vagy format()
.
>>> str(p1) '(2,3)' >>> format(p1) '(2,3)'
Tehát a str(p1)
vagy használatakor a format(p1)
Python belsőleg meghívja a p1.__str__()
módszert. Innen a név, a speciális funkciók.
Térjünk vissza a kezelő túlterheléséhez.
A + kezelő túlterhelése
Az +
operátor túlterheléséhez be kell vezetnünk a __add__()
függvényt az osztályba. Nagy hatalommal jár a nagy felelősség. Bármit megtehetünk, ebben a funkcióban. De ésszerűbb Point
a koordinátaösszeg objektumát visszaadni .
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)
Most próbáljuk meg újra az összeadási műveletet:
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)
Kimenet
(3,5)
What actually happens is that, when you use p1 + p2
, Python calls p1.__add__(p2)
which in turn is Point.__add__(p1,p2)
. After this, the addition operation is carried out the way we specified.
Similarly, we can overload other operators as well. The special function that we need to implement is tabulated below.
Operator | Expression | Internally |
---|---|---|
Addition | p1 + p2 | p1.__add__(p2) |
Subtraction | p1 - p2 | p1.__sub__(p2) |
Multiplication | p1 * p2 | p1.__mul__(p2) |
Power | p1 ** p2 | p1.__pow__(p2) |
Division | p1 / p2 | p1.__truediv__(p2) |
Floor Division | p1 // p2 | p1.__floordiv__(p2) |
Remainder (modulo) | p1 % p2 | p1.__mod__(p2) |
Bitwise Left Shift | p1 << p2 | p1.__lshift__(p2) |
Bitwise Right Shift | p1>> p2 | p1.__rshift__(p2) |
Bitwise AND | p1 & p2 | p1.__and__(p2) |
Bitwise OR | p1 | p2 | p1.__or__(p2) |
Bitwise XOR | p1 p2 | p1.__xor__(p2) |
Bitwise NOT | ~p1 | p1.__invert__() |
Overloading Comparison Operators
Python does not limit operator overloading to arithmetic operators only. We can overload comparison operators as well.
Suppose we wanted to implement the less than symbol <
symbol in our Point
class.
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)