[ Python comparison operator overloading ]
For my Python 2.7.3 project I have a class called
custom_date, which has a property called
from datetime import date class custom_date(): def __init__(self, fixed_date): self.fixed_date = fixed_date def __lt__(self, other): return self.fixed_date < other #__gt__, __ge__, __le__, __eq__, __ne__ all implemented the same way
My idea is to be able to directly compare
custom_date.fixed_date with the builtin
If I compare a
custom_date object to a
date object, it's fine. However, if I compare a
date object to a
custom_date, it returns a
>>> from datetime import date >>> x = custom_date(date(2013,2,1)) >>> y = date(2013,2,2) >>> x > y False >>> y > x TypeError: can't compare datetime.date to instance
Is there any way around this?
date to get this functionality. Since a datetime object is immutable, you need to use the
__new__ constructor vs
from datetime import date class custom_date(date): def __new__(cls, year,month,day): return date.__new__(cls, year, month,day) x = custom_date(2013,2,1) y = date(2013,2,2) print x<y print y<x
Since the determinative class for comparisons is the LH class, the class on the left needs to have the correct comparison operators to deal with the comparison with the class on the right. If there are no comparison operators for either class, instances are sorted by identity -- their memory address. Your error is essentially from trying to compare an apple to an orange: identity to a date class.
I think I know why you are running into problems. Check the data model documentation on docs.python.org.
>>> y > x
x is just an instance object, not the fixed_date attribute stored in it:
>>> x <__main__.custom_date instance at 0x020D78C8> >>> x.fixed_date datetime.date(2012, 2, 1)
One way to make it work the way you have it set up is to do:
>>> y > x.fixed_date
I think to "fix" this, you would have make all your dates of type custom_date. Somebody else may have a better solution for you, and I'll be watching, because I'm curious as well.
Found a potential solution, in case anyone else is facing the same problem.
From the Python datetime docs:
In other words, date1 < date2 if and only if date1.toordinal() < date2.toordinal(). In order to stop comparison from falling back to the default scheme of comparing object addresses, date comparison normally raises TypeError if the other comparand isn’t also a date object. However, NotImplemented is returned instead if the other comparand has a timetuple() attribute. This hook gives other kinds of date objects a chance at implementing mixed-type comparison. If not, when a date object is compared to an object of a different type, TypeError is raised unless the comparison is == or !=. The latter cases return False or True, respectively.
NotImplemented instead of raising a
TypeError, Python would automatically attempt the reverse comparison
y.__rop__(x) (More info about comparisons here).
date however raises a
TypeError if the other object isn't a
date object, unless the other object implements the timetuple() attribute.
So the solution is to add a dummy
timetuple() method to my class.
from datetime import date class custom_date(): def __init__(self, fixed_date): self.fixed_date = fixed_date def __lt__(self, other): return self.fixed_date < other #__gt__, __ge__, __le__, __eq__, __ne__ all implemented the same way def timetuple(): pass