Перевантаження оператора Python

Ви можете змінити значення оператора в Python залежно від використовуваних операндів. У цьому підручнику ви дізнаєтесь, як використовувати перевантаження оператора в Python об’єктно-орієнтованому програмуванні.

Перевантаження оператора Python

Оператори Python працюють для вбудованих класів. Але один і той же оператор поводиться по-різному з різними типами. Наприклад, +оператор виконає арифметичне додавання двох чисел, об’єднає два списки або об’єднає два рядки.

Ця функція в Python, яка дозволяє одному і тому ж оператору мати різне значення відповідно до контексту, називається перевантаженням оператора.

Отже, що відбувається, коли ми використовуємо їх з об’єктами визначеного користувачем класу? Розглянемо наступний клас, який намагається імітувати точку в 2-D системі координат.

 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, надрукований (p1 + p2) TypeError: непідтримувані типи операндів для +: 'Point' і 'Point'

Тут ми бачимо, що TypeErrorбуло піднято a , оскільки Python не знав, як скласти два Pointоб'єкти разом.

Однак ми можемо досягти цього завдання в Python за допомогою перевантаження оператора. Але спочатку давайте розберемо поняття про спеціальні функції.

Спеціальні функції Python

Функції класів, які починаються з подвійного підкреслення __, у Python називаються спеціальними функціями.

Ці функції не є типовими функціями, які ми визначаємо для класу. __init__()Функція ми визначили вище , є одним з них. Він викликається кожного разу, коли ми створюємо новий об’єкт цього класу.

У Python є безліч інших спеціальних функцій. Відвідайте спеціальні функції Python, щоб дізнатися більше про них.

Використовуючи спеціальні функції, ми можемо зробити наш клас сумісним із вбудованими функціями.

 >>> 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), Python внутрішньо викликає 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, Python викликає, 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)
Побітовий XOR p1 p2 p1.__xor__(p2)
Побітове НЕ ~p1 p1.__invert__()

Перевантаження операторів порівняння

Python не обмежує перевантаження оператора лише арифметичними операторами. Ми також можемо перевантажити оператори порівняння.

Припустимо, ми хотіли застосувати символ менше <символу у нашому 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)

Цікаві статті...