Перегрузка сокращенных операторов присваивания
Перед изучением данной темы рекомендуется ознакомиться со следующей темой:
Поиск на других ресурсах:
Содержание
- 1. Особенности перегрузки сокращенных операторов присваивания +=, -=, *=, /=, %=, //=
- 2. Перегрузка сокращенных операторов присваивания. Класс Fraction (дробь)
- 3. Пример перегрузки сокращенных операторов присвоения. Классы Point и ArrayPoint. Оперирование массивом точек
- Связанные темы
1. Особенности перегрузки сокращенных операторов присваивания +=, -=, *=, /=, %=, //=
Для перегрузки сокращенных операторов присваивания в классе нужно объявить следующие методы:
- __iadd__() – перегружает сокращенный оператор присваивания +=;
- __isub__() – перегружает оператор -=;
- __imul__() – перегружает оператор *=;
- __idiv__() – перегружает оператор /=;
- __ifloordiv__() – перегружает оператор //=;
- __imod__() – перегружает оператор %=.
Реализация каждого из этих методов в классе требует получения двух параметров:
- параметра типа self – текущий объект класса (this);
- параметра, имеющего тип данного класса. Этот параметр является объектом, используемым в правой части сокращенного оператора присваивания.
После того, как в некотором классе реализованы методы, перегружающие один из сокращенных операторов присваивания, над объектами этого класса можно выполнять следующие действия
obj1 op obj2
здесь
- obj1, obj2 – объекты класса;
- op – одна из операций +=, -=, *=, /=, //=, %=.
Например, для перегрузки оператора += в классе A может быть примерно следующий код
class A: # ... # перегрузка оператора += def __iadd__(self, obj): # Действия, которые нужно выполнить # ... # Вызов перегруженного оператора += obj1 = A() obj2 = A() obj1 += obj2
⇑
2. Перегрузка сокращенных операторов присваивания. Класс Fraction (дробь)
В примере объявляется класс Fraction (дробь). В классе объявляются две внутренние переменные:
- num (self.num) – числитель дроби;
- denom (self.denom) – знаменатель дроби.
В классе Fraction демонстрируется перегрузка методов +=, -=, *=, /=, %=, //=.
# Перегрузка операторов +=, -=, *=, /=, %=, //= # Класс, описывающий дробь, заданную числителем и знаменателем: # - num - числитель; # - denom - знаменатель. class Fraction: # Конструктор класса, num - числитель, denom - знаменатель def __init__(self, num, denom): self.num = num self.denom = denom # Корректировка num, denom if self.num == 0: self.num = 1 if self.denom == 0: self.denom = 1 self.Normal() return #-------------- Методы перегрузки операторов -------------- # Перегрузка оператора += # Добавление к данной дроби другой дроби - метод __iadd__() def __iadd__(self, frac): obj = Fraction((self.num*frac.denom+self.denom*frac.num), self.denom*frac.denom) return obj # Перегрузка оператора -= # Вычитание от данной дроби другой дроби - метод __isub__() def __isub__(self, frac): # вычитание дробей obj = Fraction((self.num*frac.denom-self.denom*frac.num), self.denom*frac.denom) return obj # Перегрузка оператора *= - метод __imul__() def __imul__(self, frac): obj = Fraction(self.num*frac.num, self.denom*frac.denom) return obj # Перегрузка оператора /= - метод __idiv__() def __idiv__(self, frac): obj = Fraction(self.num*frac.denom, self.denom*frac.num) return obj # Перегрузка оператора //= - метод __ifloordiv__() def __ifloordiv__(self, frac): # Метод возвращает результат деления дробей так же как и метод idiv() return Fraction(self.num*frac.denom, self.denom*frac.num) # Перегрузка оператора %= - метод __imod__() def __imod__(self, frac): # Метод возвращает инвертированную дробь: 5/6 => 6/5 return Fraction(self.denom, self.num) # --------------------------------------------------------- # Метод, выводящий значение внутренних координат x, y def Print(self, msg): print(msg, " => ", self.num, " / ", self.denom) return # Метод, нормализующий дробь 8/12 => 2/3 def Normal(self): t = abs(self.num) i = 1 num = i while i <= t: if ((self.num%i) == 0) and ((self.denom%i) == 0): num = i i = i+1 self.num = self.num / num self.denom = self.denom / num # (-num)/(-denom) => num/denom if (self.num<0) and (self.denom<0): self.num = -self.num self.denom = -self.denom return # Тестирование f1 = Fraction(1, 2) # конструктор f1.Print("f1") f2 = Fraction(2, 3) # конструктор f2.Print("f2") f1 += f2 # метод __iadd__() f1.Print("f1+=f2") f1 -= f2 # метод __isub__() f1.Print("f1-=f2") f1 *= f2 # метод __imul__() f1.Print("f1*=f2") f1 /= f2 # метод __idiv__() f1.Print("f1/=f2") f1 //=f2 # метод __ifloordiv__() f1.Print("f1//f2") f1 %= f1 # метод __imod__() f1.Print("f1%=f1")
Результат
f1 => 1 / 2) f2 => 2 / 3) f1+=f2 => 7 / 6 f1-=f2 => 1 / 2) f1*=f2 => 1 / 3) f1/=f2 => 1 / 2) f1//f2 => 3 / 4) f1%=f1 => 4 / 3)
⇑
3. Пример перегрузки сокращенных операторов присвоения. Классы Point и ArrayPoint. Оперирование массивом точек
В этом примере объявляются классы Point и ArrayPoint. Класс Point описывает точку на координатной плоскости. Класс ArrayPoint описывает массив точек типа Point. Массив реализован в виде списка.
В классе ArrayPoint перегружается сокращенный оператор присваивания += реализующий конкатенацию массивов типа ArrayPoint.
# Перегрузка оператора += для добавления списков объектов # Класс, описывающий точку на координатной плоскости (x; y) class Point: # Конструктор def __init__(self, x, y): self.x = x self.y = y # Методы, возвращающие координаты точки def GetX(self): return self.x def GetY(self): return self.y # Метод, который выводит координаты точки def Print(self, msg): print(msg, "=> (", self.x, "; ", self.y, ")") # Класс, реализующий массив точек: # - AP - массив точек. # В классе перегружается оператор +=, который # делает конкатенацию двух массивов точек. class ArrayPoint: # Конструктор 2 - создает пустой массив def __init__(self): self.AP = [] # массив в виде списка # Метод, добавляющий элемент к массиву def Add(self, pt): self.AP = self.AP + [pt] # Метод, возвращающий массив self.AP def Get(self): return self.AP # Метод, который выводит массив точек def Print(self, msg): print(msg) for pt in self.AP: pt.Print("") # Метод, который перегружает оператор +=, # метод добавляет к массиву self.AP точек другой массив def __iadd__(self, AP2): # 1. Объединить списки двух объектов lst = self.AP + AP2.Get() # 2. Создать результирующий объект obj = ArrayPoint() # 3. Прибавить к объекту obj элементы списка for t in lst: obj.Add(t) # Вернуть результирующий объект return obj # Тест # 1. Создать массив точек AP1 AP1 = ArrayPoint() AP1.Add(Point(2, 3)) AP1.Add(Point(4, 7)) AP1.Add(Point(8, 3)) AP1.Print("AP1") # 2. Создать массив точек AP2 AP2 = ArrayPoint() AP2.Add(Point(-2, 4)) AP2.Add(Point(7, 6)) AP2.Print("AP2") # 3. Добавить массивы AP1 += AP2 AP1.Print("AP1 += AP2")
Результат
AP1 ('', '=> (', 2, '; ', 3, ')') ('', '=> (', 4, '; ', 7, ')') ('', '=> (', 8, '; ', 3, ')') AP2 ('', '=> (', -2, '; ', 4, ')') ('', '=> (', 7, '; ', 6, ')') AP1 += AP2 ('', '=> (', 2, '; ', 3, ')') ('', '=> (', 4, '; ', 7, ')') ('', '=> (', 8, '; ', 3, ')') ('', '=> (', -2, '; ', 4, ')') ('', '=> (', 7, '; ', 6, ')')
⇑
Связанные темы
- Перегрузка операторов в классах. Общие сведения. Методы, перегружающие операторы. Примеры
- Доступ к элементам по индексу. Методы __getitem__() и __setitem()__
- Перегрузка бинарных арифметических операторов в классах: +, –, *, /, //, %
⇑