如何正确地重载 __add__ 方法?

17

我需要编写一个涉及日期的类。我应该重载+运算符以允许将天数添加到日期中。为了解释它的工作原理:一个Date对象用格式(year,month,date)表示为(2016,4,15)。将整数10添加到这个日期后应该得到(2016,4,25)。 Date类具有值self.yearself.monthself.day

我的问题是代码应该以Date + 1010 + Date的形式工作。同时,Date-1应该按照添加负数天数的方式工作。例如:Date(2016,4,25)-1返回Date(2016,4,24)

我的代码在Date + 10的形式下完美运行,但在10 + DateD - 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:不支持使用+运算符:'int'和'Date'

TypeError:不支持使用-运算符:'Date'和'int'


5
你需要同时实现__radd__ - Ozgur Vatansever
3
请查看https://dev59.com/Ipbfa4cB1Zd3GeqPrEXK#36745772。减法是一种单独的操作,您需要实现`__sub__`和`__rsub__`方法。 - snakecharmerb
我明白了。所以如果我的教授要求我“重载+运算符”,他自动意味着要创建所有这些方法吗?换句话说,重载是通过执行所有这些方法来定义的吗? - Daniel Murphy
2
是的,通常来说,“运算符重载”就是扩展或覆盖像+或-这样的运算符的行为。要做到这一点,您需要覆盖相关的特殊方法 - 参考我之前给您指引的答案。不过我们无法告诉您您的教授具体指的是什么,您需要向他们咨询。 - snakecharmerb
1
你的日期类是独立的,还是允许使用标准的datetime模块? - PM 2Ring
1个回答

20

__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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接