Mil*_*ams 7 python datetime subclass
我正在尝试datetime.datetime使用一些额外的方法来扩展Python的类.所以,例如我在做:
import datetime
class DateTime(datetime.datetime):
def millisecond(self):
return self.microsecond/1000
Run Code Online (Sandbox Code Playgroud)
但是如果我这样做的话
>>> 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'
Run Code Online (Sandbox Code Playgroud)
这显然是因为d + delta调用datetime.datetime.__add__()返回datetime.datetime对象的方法.
有什么办法可以让这个datetime.datetime对象转换成一个DateTime对象吗?或者我是否必须重新实现DateTime子类中的所有运算符才能返回正确的类型?
jdm*_*jdm 16
有点晚了,但以下工作:
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
Run Code Online (Sandbox Code Playgroud)
基本上,你使用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
Run Code Online (Sandbox Code Playgroud)
unutbu 与您最初的要求非常接近:
class DateTime(datetime.datetime):
@property
def millisecond(self):
return self.microsecond/1000.0
datetime.datetime = DateTime
Run Code Online (Sandbox Code Playgroud)
我使用此模式来实现仅在 3.3 中出现而在 3.1 或 3.2 中工作的 API。班里的其他人继续像以前一样工作,没有表现上的损失。
编辑添加:这仅适用于 2.6+ 的内置函数,因为它仅适用于新型类。内置函数在 2.6 之前都是老式的。
在这种情况下,我更喜欢简单的独立函数:
import datetime
def millisecond(dt):
return dt.microsecond/1000
Run Code Online (Sandbox Code Playgroud)
Mixin 在 Python 中是可能的(参见评论),但我认为在这种情况下它们是多余的。