我制作了一个使用日期列表作为索引的列表,如下所示:
>>> import datedlist
>>> import datetime
>>> dates = [datetime.date(2012,1,x) for x in range(2,6)]
>>> values = range(4,8)
>>> dates
[datetime.date(2012, 1, 2), datetime.date(2012, 1, 3), datetime.date(2012, 1, 4), datetime.date(2012, 1, 5)]
>>> dl = datedlist.DatedList(values, dates)
>>> dl
[4, 5, 6, 7]
>>> dl[datetime.date(2012,1,3)]
5
到目前为止一切都很好,但我也希望能够使用切片(不是扩展切片),就像这样(以下不起作用-这是我想要的结果):
>>> datedlist[datetime.date(2012,1,3):datetime.date(2012,1,4)]
[5, 6]
这是我的尝试(显然不起作用):
class DatedList(list):
def __init__(self, values, dates):
self.dates = dates
list.__init__(self, values)
def __getitem__(self, date):
if isinstance(date, slice):
start = self.dates.index(slice[0])
end = self.dates.index(slice[1])
return [list.__getitem__(self, index) for index in range(start, end)]
elif isinstance( date, datetime.date ) :
index = self.dates.index(date)
return list.__getitem__(self, index)
elif isinstance(date, int):
if date < 0:
date += len(self)
if date >= len(self):
raise IndexError, "index out of range {}".format(date)
return list.__getitem__(self, date)
else:
raise TypeError, "Invalid argument type."
slice[0] 和 slice[1] 只是为了解释我的意图。isinstance(date, int) 仅用于调试 - 将被删除以用于生产代码。
问题是:如何实现使用 datetime.date 对象作为索引的切片?
编辑(在 gnibblers 的第二条评论之后):我也尝试过 getslice(即使文档说 getslice 已经过时了)。然后该类看起来像这样(isinstance-slice 位由于语法而被注释掉):
class DatedList(list):
def __init__(self, values, dates):
self.dates = dates
list.__init__(self, values)
def __contains__(self, date):
return date in self.dates
def __getslice__(self, fromdate, todate):
i_from = self.get_index(fromdate)
i_to = self.get_index(todate)
print i_from, i_to
return [list.__getitem__(self, i) for i in range(i_from, i_to)]
def __getitem__(self, date):
if isinstance(date, slice):
pass
# start = self.dates.index(slice[0])
# end = self.dates.index(slice[1])
# return [list.__getitem__(self, i) for i in range(start, end)]
elif isinstance(date, datetime.date):
index = self.get_index(date)
return list.__getitem__(self, index)
elif isinstance(date, int):
if date < 0:
date += len(self)
if date >= len(self):
raise IndexError, "index out of range {}".format(date)
return list.__getitem__(self, date)
else:
raise TypeError, "Invalid argument type."
def get_index(self, date):
if date in self.dates:
index = self.dates.index(date)
elif date < self.dates[0]:
index = 0
elif date > self.dates[-1]:
index = len(self.dates) - 1
return index
结果是:
>>> print dl[datetime.date(2012,1,3):datetime.date(2012,1,5)]
>>> None
显然,getslice 根本没有被使用,因为打印没有被执行。似乎 getitem 在请求切片时执行,但我似乎无法在切片中使用 datetime.date 。/编辑
注意:显然子类列表不是一个好主意,但到目前为止我尝试过的任何替代方案似乎都没有更好的效果(或根本没有):
从头开始构建一个类:我无法使用 [] 符号:
dl = DatedList(values, dates) value = dl[some_date] # I want this to work value = dl.value(same_date) # I don't want this
我考虑过使用字典,但我的列表需要排序,我也需要使用切片。
我还尝试对 collections.Sequence 进行子类化,但这导致:
TypeError:描述符“ init ”需要一个“list”对象但收到一个“DatedList”