我想通过datetime
和__div__
操作扩展__mod__
模块的timedelta对象。我希望生成的类TimeDelta
可以使用普通timedelta
作为其第一个输入参数,或使用timedelta
的常用关键字参数(例如seconds=1
)进行初始化。但是,我对以下内容感到困惑:
import datetime
class TimeDelta(datetime.timedelta):
def __init__(self, timedelta, *args, **kwargs):
pass
td1 = TimeDelta(datetime.timedelta(seconds=3))
这会导致错误
Traceback (most recent call last):
File "/home/kurt/dev/scratch/Furion_scheduler/extended_timedelta.py", line 7, in <module>
td1 = TimeDelta(datetime.timedelta(seconds=3))
TypeError: unsupported type for timedelta days component: datetime.timedelta
,正如Daniel Roseman在earlier answer中指出的那样,是因为timedelta
对象定义了__new__
方法(参见其source code)。
解决此问题的一种方法是使用合成而不是继承:
class TimeDelta(object):
def __init__(self, timedelta, *args, **kwargs):
if isinstance(timedelta, datetime.timedelta):
self.timedelta = timedelta
else:
self.timedelta = datetime.timedelta.__init__(*args, **kwargs)
def __mod__(self, other):
if isinstance(other, datetime.timedelta):
return self.timedelta.total_seconds() % other.total_seconds()
elif isinstance(other, TimeDelta):
return self.timedelta.total_seconds() % other.timedelta.total_seconds()
td1 = TimeDelta(datetime.timedelta(seconds=5))
td2 = TimeDelta(datetime.timedelta(seconds=2))
print td1 % td2
然而,一个不那么优雅的方面是,在__mod__
方法中,当前必须检查other
是timedelta
或{{1}的实例}}。
有没有办法让继承工作,或者使TimeDelta
具有组合,使得如果没有定义任何调用它的方法(例如TimeDelta
),它会尝试调用total_seconds()
上的方法?
更新
最后,我发现使用合成比覆盖self.timedelta
方法更容易。我通过为__new__
定义total_seconds()
方法来重构上面的代码:
TimeDelta
如果class TimeDelta(object):
def __init__(self, timedelta=None, **kwargs):
if isinstance(timedelta, datetime.timedelta):
self.timedelta = timedelta
else:
self.timedelta = datetime.timedelta(**kwargs)
def total_seconds(self):
return self.timedelta.total_seconds()
def __mod__(self, other):
return self.total_seconds() % other.total_seconds()
有许多必须被引用的方法,这种方法会很麻烦。以这种方式,但在这种情况下timedelta
是唯一的方法(参见https://docs.python.org/2/library/datetime.html#datetime.timedelta)。