如何扩展Python';s datetime.datetime是否使用我自己的方法?

如何扩展Python';s datetime.datetime是否使用我自己的方法?,python,datetime,subclass,Python,Datetime,Subclass,我试图用两个额外的方法扩展Python的datetime.datetime类。例如,我正在做: import datetime class DateTime(datetime.datetime): def millisecond(self): return self.microsecond/1000 但是如果我这样做了 >>> d = DateTime(2010, 07, 11, microsecond=3000) >>> prin

我试图用两个额外的方法扩展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.\uuu添加
方法,该方法返回一个
datetime.datetime
对象


是否有任何方法可以将此
datetime.datetime
对象转换为
datetime
对象?或者我必须重新实现我的
DateTime
子类中的所有运算符才能返回正确的类型吗?

在这种情况下,我更喜欢简单的独立函数:

import datetime
def millisecond(dt):
    return dt.microsecond/1000

Python中可以使用mixin(参见注释),但我认为在这种情况下它们是多余的。

在simplet级别,您可以这样做

import datetime
def millisecond(self):
    return self.microsecond/1000

datetime.datetime.millisecond = millisecond
然而,动态插入的mixin可能更整洁——或者只是定义一个函数并向其传递一个datetime实例


总的来说,monkeypatching并不是一个很好的Pythonic——它更多的是一种Ruby解决问题的方法。

我尝试使用monkeypatching实现一个解决方案,但遇到了错误:

TypeError: can't set attributes of built-in/extension type 'datetime.datetime'
这发生在
datetime.datetime.millished=millished

可能是
datetime。因此
无法进行修补。如果这是真的,那么你可能想考虑一下:

import datetime

class DateTime(datetime.datetime):
    @property
    def millisecond(self):
        return self.microsecond/1000.0
    def __add__(self,other):
        result=super(DateTime,self).__add__(other)
        result=DateTime(result.year,
                        result.month,
                        result.day,
                        result.hour,
                        result.minute,
                        result.second,
                        result.microsecond,
                        result.tzinfo)        
        return result
    __radd__=__add__

d = DateTime(2010, 07, 11, microsecond=3000)
print d.millisecond
# 3.0

delta = datetime.timedelta(hours=4)
newd = d + delta
print newd.millisecond
# 3.0

# This uses __radd__
newd = delta + d
print newd.millisecond
# 3.0

unutbu与您最初的要求非常接近:

class DateTime(datetime.datetime):
    @property
    def millisecond(self):
        return self.microsecond/1000.0

datetime.datetime = DateTime
我使用此模式来实现API,这些API在3.1或3.2中工作时只在3.3中出现。班上的其他同学一如既往地工作,没有任何性能损失


编辑为添加:这只适用于内置的2.6+,因为它只适用于新样式的类。直到2.6版本,内置式都是旧式的。

有点晚了,但以下功能仍然有效:

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

TypeError:无法设置内置/扩展类型“datetime.datetime”的属性最好的用途之一是实现一些功能,这些功能通常在将来的版本中才会出现,特别是在它们相当简单和有用的情况下。这是最好的解决方案。别忘了对类方法使用@classmethod(原文如此!)。