如何正确地重载__add__方法?

时间:2016-04-22 05:18:56

标签: python class overloading

我需要写一个涉及日期的课程。我应该重载+运算符以允许将日期添加到日期。解释它的工作原理:Date对象以(2016年,4月,15年)的格式(年,月,日)表示。向此添加整数10应该产生(2016,4,25)。 Date类的值为self.yearself.monthself.day

我的问题是代码应该以{{1​​}}和Date + 10的形式运行。同样10 + Date应该在添加负天数的意义上起作用。 Date - 1会返回Date(2016, 4, 25) - 1

我的代码完美地以Date(2016, 4, 24)的形式运行,但不是Date + 1010 + 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'

1 个答案:

答案 0 :(得分:16)

__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