Python. Перегрузка бинарных арифметических операторов в классах

Перегрузка бинарных арифметических операторов в классах


Поиск на других ресурсах:

Содержание


1. Общие сведения о перегрузке бинарных арифметических операторов +, , *, /, //, %

Бинарные арифметические операторы в классах получают 2 операнда. Общая форма вызова бинарного арифметического оператора имеет вид:

res = a op b

здесь

  • a, b – операнды, над которыми осуществляется операция;
  • op – одна из операций +, –, *, /, //, %;
  • res – результирующий объект.

Для перегрузки соответствующего бинарного оператора в классе необходимо реализовать соответствующий метод.

Ниже представлен список общих методов для перегрузки бинарных операторов +, –, *, /, //, %, оперирующих объектами:

  • метод __add__() – перегрузка бинарного оператора + (сложение). Метод вызывается в выражении типа a+b;
  • метод __sub__() – перегрузка бинарного оператора – (вычитание). Метод вызывается при вычитании объектов a–b;
  • метод __mul__() – перегрузка бинарного оператора * (умножение). Метод вызывается при умножении двух операндов a*b;
  • метод __div__() – перегрузка бинарного оператора / (деление). Вызывается в выражениях типа a/b;
  • метод __mod__() – перегрузка бинарного оператора % (остаток от деления). Вызывается в выражении a%b;
  • метод __floordiv__() – перегрузка бинарного оператора // (деление с округлением вниз). Вызывается в выражении a//b.

 

2. Пример перегрузки операторов +, –. Класс Point

В примере объявляется класс Point, реализующий точку на координатной плоскости. В классе перегружаются операторы + (сложение) и – (вычитание). Для этого в классе объявляются методы __add__() и __sub__().

# Перегрузка бинарного оператора +

# Класс, описывающий точку на координатной плоскости
class Point:

    # Конструктор класса
    def __init__(self, x, y):
        self.x = x
        self.y = y
        return

    # Методы доступа к полям self.x, self.y
    def GetX(): return self.x
    def GetY(): return self.y
    def SetXY(self, x, y):
        self.x = x
        self.y = y
        return

    #-------------- Методы перегрузки операторов --------------
    # Перегрузка бинарного оператора + (суммирование объектов) - метод __add__()
    def __add__(self, pt):
        obj = Point(self.x + pt.x, self.y + pt.y)
        return obj

    # Перегрузка бинарного оператора вычитания - метод __sub__()
    def __sub__(self, pt):
        # вычитание координат
        obj = Point(self.x - pt.x, self.y - pt.y)
        return obj

    # ---------------------------------------------------------
    # Метод, который выводит значения внутренних координат x, y
    def Print(self, msg):
        print(msg, " => x = ", self.x, "; y = ", self.y)
        return

# Тестирование
pt1 = Point(1,3)
pt1.Print("pt1")

pt2 = Point(2,6)
pt2.Print("pt2")

pt3 = pt1 + pt2
pt3.Print("pt1 + pt2")

(pt1-pt2).Print("pt1 - pt2")

Результат

pt1 => x = 1, y = 3
pt2 => x = 2, y = 6
pt1 + pt2 => x = 3, y = 9
pt1 - pt2 => x = -1, y = -3

 

3. Пример перегрузки операторов +, , *, /, //, % для класса Fraction (Дробь)

В примере объявляется класс Fraction (Дробь) в котором перегружаются стандартные бинарные арифметические операторы.
Для операторов +, –, *, / выполняются соответствующие операции сложения, вычитания, умножения, деления двух дробей. Оператор // (деление нацело) возвращает дробное число от деления операндов. Оператор % (взятие остатка) возвращает целое число от деления операндов.

Класс содержит метод Normal(), который приводит дробь к нормальному виду типа

-8/-12 = 2/3

Текст программы следующий

# Перегрузка бинарного оператора +

# Класс, описывающий дробь
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

    # Методы доступа к полям self.num, self.denom
    def GetNum(): return self.num
    def GetDenom(): return self.denom
    def Set(self, num, denom):
        self.num = num
        self.denom = denom
        return

    #-------------- Методы перегрузки операторов --------------
    # Перегрузка бинарного оператора + (суммирование дробей) - метод __add__()
    def __add__(self, frac):
        obj = Fraction((self.num*frac.denom+self.denom*frac.num), self.denom*frac.denom)
        return obj

    # Перегрузка бинарного оператора вычитания - метод __sub__()
    def __sub__(self, frac):
        # вычитание дробей
        obj = Fraction((self.num*frac.denom-self.denom*frac.num), self.denom*frac.denom)
        return obj

    # Перегрузка бинарного * (умножения) - метод __mul__()
    def __mul__(self, frac):
        obj = Fraction(self.num*frac.num, self.denom*frac.denom)
        return obj

    # Перегрузка бинарного / (деление) - метод __div__()
    def __div__(self, frac):
        obj = Fraction(self.num*frac.denom, self.denom*frac.num)
        return obj

    # Перегрузка бинарного // (деление нацело) - метод __floordiv__()
    def __floordiv__(self, frac):
        # Метод возвращает результат деления типа float
        return float((self.num*frac.denom) / (self.denom*frac.num))

    # Перегрузка бинарного оператора % (взятие остатка) - метод __mod__()
    def __mod__(self, frac):
        # Метод возвращает результат деления типа int
        return int((self.num*frac.denom) / (self.denom*frac.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(6, -12)
f1.Print("f1")
f2 = Fraction(2, -12)
f2.Print("f2")

f3 = f1 + f2
f3.Print("f1 + f2")

f3 = f1 - f2
f3.Print("f1 - f2")

f3 = f1 * f2
f3.Print("f1 * f2")

f3 = f1 / f2
f3.Print("f1 / f2")

res = f1 // f2
print("f1 // f2 => ", res) # res = 3.0

res = f1 % f2
print("f1 % f2 => ", res) # res = 3

Результат

f1 => 1 / -2
f2 => 1 / -6)
f1 + f2 => -2 / 3
f1 - f2 => -1 / 3
f1 * f2 => 1 / 12
f1 / f2 => 3 / 1)
f1 // f2 => 3.0
f1 % f2 => 3

 


Связанные темы