__rsub__ и __rruediv__ с дробями

Я пытаюсь использовать функцию __rsub__ в созданном мною классе Fraction.

Вот код класса Fraction:

def __init__(self, num, denom):
    ''' Creates a new Fraction object num/denom'''
    self.num = num
    self.denom = denom
    self.reduce()

def __repr__(self):
    ''' returns string representation of our fraction'''
    return str(self.num) + "/" + str(self.denom)

def reduce(self):
    ''' converts our fractional representation into reduced form'''
    divisor = gcd(self.num, self.denom)
    self.num = self.num // divisor
    self.denom = self.denom // divisor
def __sub__(self, other):
    if isinstance(other,Fraction) == True:
        newnum = self.num * other.denom - self.denom*other.num
        newdenom = self.denom * other.denom
        return Fraction(newnum, newdenom)

Теперь, если я сделаю __radd__ или __rmul__, используя: return self + other или return self * other соответственно, это даст желаемый результат. Однако выполнение __rsub__ и __rtruediv__ не работает путем простой смены оператора. Как я могу это исправить?

По сути, код, вызывающий функции:

f = Fraction(2,3)
g = Fraction(4,8)
print("2 - f: ", 2 - f)
print("2 / f: ", 2 / f)

Спасибо за любую помощь!


person Zack Tanner    schedule 04.11.2011    source источник
comment
Пожалуйста, никогда не пишите == True!   -  person Fred Foo    schedule 04.11.2011


Ответы (3)


Сначала вам нужно преобразовать other в Fraction, чтобы это работало:

def __rsub__(self, other):
    return Fraction(other, 1) - self

Поскольку __rsub__() вызывается только в том случае, если other не имеет тип Fraction, нам не нужна проверка типов — мы просто предполагаем, что это целое число.

Ваша текущая реализация __sub__() также нуждается в некоторой доработке — она ничего не возвращает, если other не имеет типа Fraction.

person Sven Marnach    schedule 04.11.2011

Потому что вы проверяете тип и возвращаете None, когда второй операнд не Fraction (также if isinstance(...):, а не if isinstance(...) == True:). Вместо этого вам нужно навязать аргумент.

person Cat Plus Plus    schedule 04.11.2011
comment
Спасибо за внимание к isinstance. Я сделал адаптацию :) - person Zack Tanner; 04.11.2011

Обычный способ реализации операции "r": 1) проверить, что other является типом, с которым вы знаете, как обращаться; 2) если нет, вернуть NotImplemented; и 3) если да, преобразовать в тип, который может взаимодействовать с собой:

def __radd__(self, other):
    if not instance(other, (int, Fraction):
        return NotImplemented
    converted = Fraction(other)
    return converted + self
person Raymond Hettinger    schedule 04.11.2011