如何扩展Python的datetime.datetime以添加自定义方法?
我正在尝试给Python的 datetime.datetime
类添加一些额外的方法。比如,我这样做:
import datetime
class DateTime(datetime.datetime):
def millisecond(self):
return self.microsecond/1000
但是如果我这样做:
>>> d = DateTime(2010, 07, 11, microsecond=3000)
>>> print d.millisecond()
3
>>> delta = datetime.timedelta(hours=4)
>>> newd = d + delta
>>> print newd.millisecond()
AttributeError: 'datetime.datetime' object has no attribute 'millisecond'
这显然是因为执行 d + delta
时,会调用 datetime.datetime.__add__()
方法,而这个方法返回的是一个 datetime.datetime
对象。
有没有办法让我这个 datetime.datetime
对象转换成 DateTime
对象?还是说我必须在我的 DateTime
子类中重新实现所有的运算符,以返回正确的类型?
5 个回答
6
unutbu 的回答和你最初问的问题非常接近:
class DateTime(datetime.datetime):
@property
def millisecond(self):
return self.microsecond/1000.0
datetime.datetime = DateTime
我用这个方法来实现一些API,这些API在3.3版本中才会出现,而我在3.1或3.2版本中工作时也能正常使用。这个类的其他部分依然可以照常工作,没有任何性能下降。
补充说明:这个方法只适用于2.6及以上版本的内置类,因为它只适用于新式类。在2.6之前,内置类都是旧式的。
17
虽然有点晚了,但下面的方法可以用:
import ctypes as c
_get_dict = c.pythonapi._PyObject_GetDictPtr
_get_dict.restype = c.POINTER(c.py_object)
_get_dict.argtypes = [c.py_object]
import datetime
def millisecond(td):
return (td.microsecond / 1000)
d = _get_dict(datetime.datetime)[0]
d['millisecond'] = millisecond
now = datetime.datetime.now()
print now.millisecond(), now.microsecond
简单来说,你可以用ctypes来获取一个可以编辑的类字典的副本,然后把你想要的方法放进去。我主要用这个方法是为了把一些功能移植到旧版本的Python上,我觉得这样做还挺干净的。例如:
from datetime import timedelta
try:
timedelta.total_seconds # new in 2.7
except AttributeError:
def total_seconds(td):
return float(td.days * 24 * 3600 + td.seconds + td.microseconds / 1e6)
d = _get_dict(timedelta)[0]
d['total_seconds'] = total_seconds
# works now in 2.4
3
在这种情况下,我更喜欢使用简单的独立函数:
import datetime
def millisecond(dt):
return dt.microsecond/1000
在Python中可以使用混入(mixins),但我觉得在这种情况下它们是多余的。