Preobremenitev operaterja Python

Pomen operatorja v Pythonu lahko spremenite glede na uporabljene operande. V tej vadnici boste izvedeli, kako uporabljati preobremenitev operaterja v Python objektno usmerjenem programiranju.

Preobremenitev operaterja Python

Pythonovi operaterji delajo za vgrajene razrede. Toda isti operater se pri različnih vrstah obnaša drugače. Na primer, +operater bo izvedel aritmetično seštevanje dveh števil, združil dva seznama ali združil dva niza.

Ta funkcija v Pythonu, ki omogoča istemu operaterju različen pomen glede na kontekst, se imenuje preobremenitev operaterja.

Kaj se torej zgodi, ko jih uporabimo s predmeti uporabniško določenega razreda? Upoštevajmo naslednji razred, ki poskuša simulirati točko v 2-D koordinatnem sistemu.

 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)

Izhod

 Sledenje (zadnji zadnji klic): Datoteka "", vrstica 9, v tisku (p1 + p2) TypeError: nepodprte vrste operandov za +: 'Point' in 'Point'

Tu lahko vidimo, da je TypeErrorbila postavljena a, ker Python ni znal dodati dveh Pointpredmetov skupaj.

Vendar lahko to nalogo v Pythonu dosežemo s preobremenitvijo operaterja. Najprej pa si oglejmo posebne funkcije.

Posebne funkcije Pythona

Funkcije razredov, ki se začnejo z dvojnim podčrtajem, __se v Pythonu imenujejo posebne funkcije.

Te funkcije niso tipične funkcije, ki jih definiramo za razred. __init__()Funkcija smo definirali zgoraj, je eden izmed njih. Pokliče se vsakič, ko ustvarimo nov predmet tega razreda.

V Pythonu obstajajo številne druge posebne funkcije. Obiščite Python Special Functions, če želite izvedeti več o njih.

Z uporabo posebnih funkcij lahko svoj razred združimo z vgrajenimi funkcijami.

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

Recimo, da želimo, da print()funkcija natisne koordinate Pointpredmeta namesto tega, kar smo dobili. V __str__()svojem razredu lahko določimo metodo, ki nadzoruje, kako se predmet natisne. Poglejmo, kako lahko to dosežemo:

 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)

Zdaj poskusimo print()znova funkcijo.

 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)

Izhod

 (2, 3)

To je bolje. Izkazalo se je, da se ta isti način prikliče, ko uporabimo vgrajeno funkcijo str()oz format().

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

Torej, ko uporabljate str(p1)ali format(p1), Python interno pokliče p1.__str__()metodo. Od tod tudi ime, posebne funkcije.

Zdaj pa se vrnimo k preobremenitvi operaterja.

Preobremenitev operaterja +

Če želimo +operater preobremeniti , bomo morali __add__()v razredu implementirati funkcijo. Z veliko močjo prihaja velika odgovornost. V tej funkciji lahko počnemo, kar želimo. Vendar je bolj smiselno vrniti Pointpredmet koordinatne vsote.

 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)

Zdaj poskusimo znova dodati postopek:

 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)

Izhod

 (3,5)

V resnici se zgodi, da med uporabo p1 + p2Python pokliče, p1.__add__(p2)kar pa je Point.__add__(p1,p2). Po tem se postopek dodajanja izvede na način, ki smo ga določili.

Podobno lahko preobremenimo tudi druge operaterje. Posebna funkcija, ki jo moramo izvesti, je prikazana spodaj.

Operater Izraz Interno
Dodatek p1 + p2 p1.__add__(p2)
Odštevanje p1 - p2 p1.__sub__(p2)
Množenje p1 * p2 p1.__mul__(p2)
Moč p1 ** p2 p1.__pow__(p2)
Divizija p1 / p2 p1.__truediv__(p2)
Talna divizija p1 // p2 p1.__floordiv__(p2)
Preostanek (po modulu) p1 % p2 p1.__mod__(p2)
Bitwise Left Shift p1 << p2 p1.__lshift__(p2)
Bit-Right Shift p1>> p2 p1.__rshift__(p2)
Bitovno AND p1 & p2 p1.__and__(p2)
Bitovno ALI p1 | p2 p1.__or__(p2)
Bitno XOR p1 p2 p1.__xor__(p2)
Bitno NE ~p1 p1.__invert__()

Preobremenitev operaterjev primerjave

Python ne omejuje preobremenitve operaterja le na aritmetične operatorje. Preobremenimo lahko tudi operaterje primerjave.

Recimo, da smo <v našem Pointrazredu želeli uporabiti simbol manj kot simbol .

Primerjajmo velikost teh točk od začetka in v ta namen vrnemo rezultat. Izvede se lahko na naslednji način.

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

Zanimive Članki...