次のように、日付のリストをインデックスとして使用するリストを作成しました。
>>> 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."
スライス [0] とスライス [1] は、私の意図を説明するためだけのものです。isinstance(date, int) はデバッグ用にのみ存在します。製品コードでは削除されます。
ここに質問があります: datetime.date オブジェクトをインデックスとして使用するスライスをどのように実装できますか?
編集(ニブラーの2番目のコメントの後):私も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' を受け取りました