Как правильно перегрузить метод __add__?

Я обязан написать класс с датами. Я должен перегрузить оператор + чтобы разрешить добавление дней к датам. Чтобы объяснить, как это работает: объект Date представлен в виде (2016, 4, 15) в формате (год, месяц, дата). Добавление целого числа 10 к этому должно привести к (2016, 4, 25). Класс Date имеет значения self.year, self.month, self.day.

Моя проблема в том, что код должен работать в форме Date + 10 а также 10 + Date. Также Date - 1 должна работать в смысле добавления отрицательного числа дней. Date(2016, 4, 25) - 1 возврат Date(2016, 4, 24).

Мой код прекрасно работает в форме Date + 10 но не в форме 10 + D или D - 1.

def __add__(self,value):
    if type(self) != int and type(self) != Date or (type(value) != int and type(value) != Date):
        raise TypeError
    if type(self) == Date:
        day = self.day
        month = self.month
        year = self.year
        value = value
    if type(value) != int:
        raise TypeError
    days_to_add = value
    while days_to_add > 0:
        day+=1
        if day == Date.days_in(year,month):
            month+=1
            if month > 12:
                day = 0
                month = 1
                year+=1
            day = 0
        days_to_add -=1
    return(Date(year,month,day))

Это ошибки, которые я получаю

TypeError: unsupported operand type(s) for +: 'int' and 'Date'

TypeError: unsupported operand type(s) for -: 'Date' and 'int'

Ответ 1

__radd__ обрабатывает добавление справа, так что вам нужно это реализовать.

Я вижу некоторые недостатки в вашей реализации, поэтому я рекомендую вам использовать модуль datetime (особенно класс datetime.timedelta) для хотя бы правильной обработки базовой арифметики даты:

import datetime

class Date(object):
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

    def as_date(self):
        return datetime.date(self.year, self.month, self.day)

    def __add__(self, other):
        if isinstance(other, int):
            date = self.as_date() + datetime.timedelta(days=other)
            return Date(date.year, date.month, date.day)
        else:
            raise ValueError("int value is required")

    def __radd__(self, other):
        return self.__add__(other)

    def __sub__(self, other):
        return self.__add__(-other)

    def __rsub__(self, other):
        raise RuntimeError("Doesn't make sense.")

    def __repr__(self):
        return str(self.as_date())

Демо-версия:

>>> date = Date(2015, 10, 23)
>>> print date + 10 # __add__ is called
2015-11-02

>>> print 20 + date # __radd__ is called
2015-11-12

>>> print date - 25 # __sub__ is called
2015-09-28

>>> print 25 - date # __rsub__ is called 
RuntimeError: Doesn't make sense