Preťaženie operátora Python

Význam operátora v Pythone môžete zmeniť v závislosti od použitých operandov. V tomto výučbe sa dozviete, ako používať preťaženie operátorov v programovaní zameranom na objekt Python.

Preťaženie operátora Python

Operátori Pythonu pracujú pre vstavané triedy. Rovnaký operátor sa ale pri rôznych typoch správa inak. Napríklad +operátor vykoná aritmetické sčítanie na dvoch číslach, zlúči dva zoznamy alebo spojí dva reťazce.

Táto funkcia v Pythone, ktorá umožňuje tomu istému operátorovi mať odlišný význam podľa kontextu, sa nazýva preťaženie operátora.

Čo sa teda stane, keď ich použijeme s objektmi triedy definovanej používateľom? Uvažujme o nasledujúcej triede, ktorá sa pokúša simulovať bod v 2-D súradnicovom systéme.

 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)

Výkon

 Traceback (posledný hovor naposledy): File "", riadok 9, v tlači (p1 + p2) TypeError: nepodporované typy operandov pre +: 'Point' a 'Point'

Tu vidíme, že TypeErrorbolo zvýšené a, pretože Python nevedel pridať dva Pointobjekty k sebe.

Túto úlohu však môžeme v Pythone dosiahnuť preťažením operátora. Najskôr si ale urobme predstavu o špeciálnych funkciách.

Špeciálne funkcie v Pythone

Funkcie triedy, ktoré začínajú dvojitým podčiarkovníkom, __sa v Pythone nazývajú špeciálne funkcie.

Tieto funkcie nie sú typickými funkciami, ktoré definujeme pre triedu. __init__()Funkciu sme definovali vyššie, je jedným z nich. Zavolá sa vždy, keď vytvoríme nový objekt tejto triedy.

V Pythone existuje množstvo ďalších špeciálnych funkcií. Navštívte Špeciálne funkcie Pythonu a dozviete sa o nich viac.

Pomocou špeciálnych funkcií môžeme dosiahnuť, aby bola naša trieda kompatibilná so zabudovanými funkciami.

 >>> p1 = Point(2,3) >>> print(p1) 

Predpokladajme, že chceme, aby print()funkcia tlačila súradnice Pointobjektu namiesto toho, čo sme dostali. V __str__()našej triede môžeme definovať metódu, ktorá riadi, ako sa bude objekt tlačiť. Pozrime sa, ako to môžeme dosiahnuť:

 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)

Teraz skúsime print()funkciu znova.

 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)

Výkon

 (2, 3)

To je lepšie. Ukázalo sa, že rovnaká metóda je vyvolaná, keď použijeme vstavanú funkciu str()alebo format().

 >>> str(p1) '(2,3)' >>> format(p1) '(2,3)'

Takže keď použijete str(p1)alebo format(p1), Python interne zavolá p1.__str__()metódu. Odtiaľ pochádza aj názov, špeciálne funkcie.

Teraz sa vráťme k preťaženiu operátora.

Preťaženie operátora +

Na preťaženie +operátora budeme musieť __add__()v triede implementovať funkciu. S veľkou mocou prichádza veľká zodpovednosť. V rámci tejto funkcie môžeme robiť, čo sa nám páči. Je však rozumnejšie vrátiť Pointobjekt súradnicového súčtu.

 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)

Teraz skúsime operáciu pridania znova:

 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)

Výkon

 (3,5)

Čo sa vlastne stane, je to, že keď použijete p1 + p2, zavolá Python, p1.__add__(p2)čo zase je Point.__add__(p1,p2). Potom sa vykoná operácia pridania spôsobom, ktorý sme špecifikovali.

Podobne môžeme preťažiť aj ostatných operátorov. Špeciálna funkcia, ktorú musíme implementovať, je uvedená v tabuľke nižšie.

Prevádzkovateľ Vyjadrenie Interne
Dodatok p1 + p2 p1.__add__(p2)
Odčítanie p1 - p2 p1.__sub__(p2)
Násobenie p1 * p2 p1.__mul__(p2)
Moc p1 ** p2 p1.__pow__(p2)
Divízia p1 / p2 p1.__truediv__(p2)
Podlahové rozdelenie p1 // p2 p1.__floordiv__(p2)
Zvyšok (modulo) p1 % p2 p1.__mod__(p2)
Bitový posun vľavo p1 << p2 p1.__lshift__(p2)
Bitový posun doprava p1>> p2 p1.__rshift__(p2)
Bitové AND p1 & p2 p1.__and__(p2)
Bitové ALEBO p1 | p2 p1.__or__(p2)
Bitový XOR p1 p2 p1.__xor__(p2)
Bitove NIE ~p1 p1.__invert__()

Prevádzkovatelia porovnania preťaženia

Python neobmedzuje preťaženie operátora iba na aritmetické operátory. Môžeme preťažiť aj operátorov porovnania.

Predpokladajme, že sme chceli do <našej Pointtriedy implementovať symbol menej ako symbol .

Porovnajme veľkosť týchto bodov od počiatku a vráťme výsledok na tento účel. Môže sa implementovať nasledovne.

 # 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)

Zaujímavé články...