Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly overload the __add__ method?

I am required to write a class involving dates. I am supposed to overload the + operator to allow days being added to dates. To explain how it works: A Date object is represented as (2016, 4, 15) in the format (year, month, date). Adding integer 10 to this should yield (2016, 4, 25). The Date class has values self.year, self.month, self.day.

My problem is that the code is supposed to work in the form Date + 10 as well as 10 + Date. Also Date - 1 should work in the sense of adding a negative number of days. Date(2016, 4, 25) - 1 returns Date(2016, 4, 24).

My code works perfectly in the form of Date + 10 but not in the form 10 + D or 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))

These are the errors I get

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

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

like image 706
Dorian Winters Avatar asked Apr 22 '16 05:04

Dorian Winters


People also ask

What operator can one use in order to use the overloaded __ add __ method?

Overloading the + Operator To overload the + operator, we will need to implement __add__() function in the class.

What does __ Add__ method do?

__add__ magic method is used to add the attributes of the class instance. For example, let's say object1 is an instance of a class A and object2 is an instance of class B and both of these classes have an attribute called 'a', that holds an integer.

How could you overload the addition operator in the Python language?

To overload an operator + , you need to provide an implementation to a particular special method in your class. Whenever you use + , a special method called __add__ is invoked. Now you can add up two instances of Bill . The + operator invokes the __add__ method, which knows how to add up two instances of Bill .

Which method should we need override to overload the '-' operator?

In Python, overloading is achieved by overriding the method which is specifically for that operator, in the user-defined class. For example, __add__(self, x) is a method reserved for overloading + operator, and __eq__(self, x) is for overloading == .


1 Answers

__radd__ handles right side addition so you need to implement that as well.

I am seeing some flaws in your implementation so I recommend you using datetime module (especially datetime.timedelta class) to at least handle basic date arithmetic correctly:

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())

Demo:

>>> 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
like image 62
Ozgur Vatansever Avatar answered Oct 19 '22 04:10

Ozgur Vatansever