如何正确重载 __add__ 方法?

Posted

技术标签:

【中文标题】如何正确重载 __add__ 方法?【英文标题】:How to properly overload the __add__ method? 【发布时间】:2016-08-15 14:07:15 【问题描述】:

我需要写一门涉及日期的课程。我应该重载 + 运算符以允许将天数添加到日期中。解释它是如何工作的: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 + DD - 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'

【问题讨论】:

你还需要实现__radd__ 看看***.com/a/36745772/5320906。减法是一个单独的操作,您需要实现 __sub____rsub__ 方法。 我明白了。因此,如果我的教授指示我“重载 + 运算符”,他就自动意味着要创建所有这些方法?或者换一种说法,重载是通过执行所有这些方法来定义的? 是的,一般“重载运算符”是指扩展或覆盖运算符的行为,例如 + 或 -。为此,您需要覆盖相关的特殊方法 - 参见我之前提到的答案。我们不能告诉你教授的意思,你需要问他们。 你的 Date 类是独立的,还是允许使用标准 datetime 模块中的东西? 【参考方案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

【讨论】:

以上是关于如何正确重载 __add__ 方法?的主要内容,如果未能解决你的问题,请参考以下文章

__add__,关于运算符重载(用户权限)

重载 __eq__ 以返回自定义对象

运算符重载

python操作符重载特殊方法列表

Python面向对象运算符重载

Python 运算符重载中__add__(self,other)的other.x如何理解?