Can I overload the compare (cmp()) function for a Lists ([]) index function?

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Sat Sep 29 04:52:24 CEST 2007


En Fri, 28 Sep 2007 14:36:54 -0300, xkenneth <xkenneth at gmail.com> escribi�:

> On Sep 28, 12:30 pm, xkenneth <xkenn... at gmail.com> wrote:
>> Looking to do something similair. I'm working with alot of timestamps
>> and if they're within a couple seconds I need them to be indexed and
>> removed from a list.
>> Is there any possible way to index with a custom cmp() function?

The comparison is made by the list elements themselves (using their __eq__  
or __cmp__), not by the index method nor the list object.
So you should modify __cmp__ for all your timestamps (datetime.datetime, I  
presume?), but that's not very convenient. A workaround is to wrap the  
object you are searching into a new, different class - since the list  
items won't know how to compare to it, Python will try reversing the  
operands.
datetime objects are a bit special in this behavior: they refuse to  
compare to anything else unless the other object has a `timetuple`  
attribute (see <http://docs.python.org/lib/datetime-date.html> note (4))

<code>
import datetime

class datetime_tol(object):
     timetuple=None # unused, just to trigger the reverse comparison to  
datetime objects
     default_tolerance = datetime.timedelta(0, 10)

     def __init__(self, dt, tolerance=None):
         if tolerance is None:
             tolerance = self.default_tolerance
         self.dt = dt
         self.tolerance = tolerance

     def __cmp__(self, other):
         tolerance = self.tolerance
         if isinstance(other, datetime_tol):
             tolerance = min(tolerance, other.tolerance)
             other = other.dt
         if not isinstance(other, datetime.datetime):
             return cmp(self.dt, other)
         delta = self.dt-other
         return -1 if delta<-tolerance else 1 if delta>tolerance else 0

def index_tol(dtlist, dt, tolerance=None):
     return dtlist.index(datetime_tol(dt, tolerance))


d1 = datetime.datetime(2007, 7, 18, 9, 20, 0)
d2 = datetime.datetime(2007, 7, 18, 9, 30, 25)
d3 = datetime.datetime(2007, 7, 18, 9, 30, 30)
d4 = datetime.datetime(2007, 7, 18, 9, 30, 35)
d5 = datetime.datetime(2007, 7, 18, 9, 40, 0)
L = [d1,d2,d3,d4,d5]

assert d3 in L
assert L.index(d3)==2
assert L.index(datetime_tol(d3))==1 # using 10sec tolerance
assert index_tol(L, d3)==1
assert index_tol(L, datetime.datetime(2007, 7, 18, 9, 43, 20),  
datetime.timedelta(0, 5*60))==4 # 5 minutes tolerance
</code>

-- 
Gabriel Genellina




More information about the Python-list mailing list