I'm working on a library that implements a data structure that works with any ordered data type--a rangeset. Many of the operations (like inversion) get interesting when you allow for positive and negative infinity.
One goal is to get datetime objects to work with this module, and in supporting infinity with non-numeric objects, I've created INFINITY and NEGATIVE_INFINITY:
class _Indeterminate(object):
def __eq__(self, other):
return other is self
@functools.total_ordering
class _Infinity(_Indeterminate):
def __lt__(self, other):
return False
def __gt__(self, other):
return True
def __str__(self):
return 'inf'
__repr__ = __str__
@functools.total_ordering
class _NegativeInfinity(_Indeterminate):
def __lt__(self, other):
return True
def __gt__(self, other):
return False
def __str__(self):
return '-inf'
INFINITY = _Infinity()
NEGATIVE_INFINITY = _NegativeInfinity()
Unfortunately, this doesn't work for datetime objects when on the left hand side of the cmp() operation:
In [1]: from rangeset import *
In [2]: from datetime import datetime
In [3]: now = datetime.now()
In [4]: cmp(INFINITY, now)
Out[4]: 1
In [5]: cmp(now, INFINITY)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/home/axiak/Documents/rangeset/<ipython-input-5-c928d3687d92> in <module>()
----> 1 cmp(now, INFINITY)
TypeError: can't compare datetime.datetime to _Infinity
I had hoped I could get around this limitation by using a cmp wrapper that just ensures that my objects are always called, but I really want to use the .sort()
method which will cause cmp to be called between these objects.
Is there any way to create an object which is truly less than any other object, and truly greater than any other object?
Module home: https://github.com/axiak/py-rangeset
from the docs
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.
so to allow comparison with datetime objects add a timetuple
method eg
class _Infinity(object):
def __lt__(self, other):
return False
def __gt__(self, other):
return True
def timetuple(self):
return tuple()
import datetime
INF = _Infinity()
now = datetime.datetime.now()
print cmp(INF, now)
print cmp(now, INF)
output:
1
-1
I'm not really sure but try to overwrite __eq__
and __ne__
(or __cmp__
) to see if they are called whenever you do cmp. You also should be aware that cmp and __cmp__
is removed from python 3.
Problem is that cmp(now, INFINITY)
is equivalent to datetime.__cmp__(INFINITY)
which is defined directly on the datettime class. You could get around this by monkey-patching the dateetime module but thats really hackish.
I think what you really want is just a sort function which takes into account your class and always puts it in front or back depending on the sign of the infinity.
def order(x, y):
if isinstance(x,_Infinity):
return -1
if isinstance(y, _Infinity):
return 1
elif isinstance(x, _NegativeInfinity):
return 1
elif isinstance(y, _NegativeInfinity):
return -1
else:
return cmp(x,y)
>>> sorted([datetime.datetime.now(), datetime.datetime.now(), INFINITY, NEGATIVE_INFINITY], cmp=order)
[
NEGATIVE_INFINITY,
datetime.datetime(2011, 12, 8, 13, 38, 47, 428626),
datetime.datetime(2011, 12, 8, 13, 38, 47, 428661),
INFINITY
]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.