Преоптерећење Питхон оператора

Значење оператора у Питхону можете променити у зависности од коришћених операнда. У овом упутству ћете научити како се користи преоптерећење оператора у Питхон објектно оријентисаном програмирању.

Преоптерећење Питхон оператора

Питхон оператери раде за уграђене класе. Али исти оператер се различито понаша са различитим типовима. На пример, +оператер ће извршити аритметичко сабирање два броја, објединити две листе или спојити два низа.

Ова карактеристика у Питхону која омогућава истом оператору да има различита значења у складу са контекстом назива се преоптерећење оператора.

Дакле, шта се дешава када их користимо са објектима кориснички дефинисане класе? Размотримо следећу класу која покушава да симулира тачку у 2-Д координатном систему.

 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)

Оутпут

 Трацебацк (најновији последњи позив): Датотека „“, ред 9, у штампи (п1 + п2) ТипеЕррор: неподржани типови операнда за +: „Тачка“ и „Тачка“

Овде можемо видети да је TypeErrorа подигнут, јер Питхон није знао како да Pointсабере два објекта.

Међутим, овај задатак у Питхону можемо постићи преоптерећењем оператора. Али прво, хајде да добијемо појам о посебним функцијама.

Питхон посебне функције

Функције класе које почињу двоструким доњим цртама __називају се посебним функцијама у Питхону.

Ове функције нису типичне функције које дефинишемо за класу. __init__()Функција ми је претходно дефинисано је један од њих. Позва се сваки пут када креирамо нови објекат те класе.

У Питхону постоје бројне друге посебне функције. Посетите Питхон Специал Фунцтионс да бисте сазнали више о њима.

Користећи посебне функције, нашу класу можемо учинити компатибилном са уграђеним функцијама.

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

Претпоставимо да желимо да print()функција исписује координате Pointобјекта уместо онога што смо добили. Можемо дефинисати __str__()метод у нашој класи који контролише како се објекат штампа. Погледајмо како то можемо постићи:

 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)

Покушајмо поново са print()функцијом.

 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)

Оутпут

 (2, 3)

Тако је боље. Испоставило се, да се тај исти метод позива када користимо уграђену функцију str()или format().

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

Дакле, када користите str(p1)или format(p1), Питхон интерно позива p1.__str__()методу. Отуда и назив, посебне функције.

Вратимо се сада преоптерећењу оператера.

Преоптерећење оператора +

Да бисмо преоптеретили +оператор, мораћемо да имплементирамо __add__()функцију у класи. С великом моћи долази и велика одговорност. Унутар ове функције можемо да радимо шта год желимо. Али, разумније је вратити Pointпредмет координатног збира.

 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)

Покушајмо поново са сабирањем:

 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)

Оутпут

 (3,5)

Оно што се заправо догађа је да, када користите p1 + p2, Питхон позива p1.__add__(p2)што заузврат јесте Point.__add__(p1,p2). Након тога, операција сабирања се изводи на начин који смо одредили.

Слично томе, можемо преоптеретити и друге операторе. Посебна функција коју морамо да применимо је дата у табели у наставку.

Оператор Израз Интерно
Сабирање p1 + p2 p1.__add__(p2)
Одузимање p1 - p2 p1.__sub__(p2)
Множење p1 * p2 p1.__mul__(p2)
Снага p1 ** p2 p1.__pow__(p2)
Дивизија p1 / p2 p1.__truediv__(p2)
Флоор Дивисион p1 // p2 p1.__floordiv__(p2)
Остатак (по модулу) p1 % p2 p1.__mod__(p2)
Преко левог померања p1 << p2 p1.__lshift__(p2)
Промена удесно померање p1>> p2 p1.__rshift__(p2)
У битовима И. p1 & p2 p1.__and__(p2)
У битовима ИЛИ p1 | p2 p1.__or__(p2)
Битно КСОР p1 p2 p1.__xor__(p2)
Битно НЕ ~p1 p1.__invert__()

Преоптерећење оператора упоређивања

Питхон не ограничава преоптерећење оператора само на аритметичке операторе. Можемо преоптеретити и операторе поређења.

Претпоставимо да смо желели да применимо симбол мањи од <симбола у нашој Pointкласи.

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)

Занимљиви Чланци...