子类化datetime:在算术运算之后是否有更好的方法来维护生成的对象类型?

时间:2011-11-29 00:53:53

标签: python

我最近遇到了一个情境,我需要继承datetime.datetimedatetime.timedelta,以便添加一些方法。但是,我立即发现,当我希望它返回datetime.datetime实例时,任何算术运算都会返回一个mydatetime.mydatetime对象。以下是同事帮助我解决这个问题的解决方案。有没有人有更简洁或方便的建议?我在这里做了什么有危险吗?我错过了什么重要的事情吗?

from datetime import datetime, timedelta

def _to_mydatetime(native):
    '''Instantiates object of appropriate class based on class
    of the input object.'''
    if hasattr(native, 'timetuple'):
        return mydatetime(*native.timetuple()[:6])
    else:
        return mytimedelta(native.days, native.seconds)

class mydatetime(datetime):
    '''Subclass of datetime'''
    def __add__(self, other):
        result = super(mydatetime, self).__add__(other)
        return _to_mydatetime(result)

    def __sub__(self, other):
        result = super(mydatetime, self).__sub__(other)
        return _to_mydatetime(result)

class mytimedelta(timedelta):
    def __add__(self, other):
        result = super(mytimedelta, self).__add__(other)
        return _to_mydatetime(result)

    def __sub__(self, other):
        result = super(mytimedelta, self).__sub__(other)
        return _to_mydatetime(result)

    def __div__(self, other):
        result = super(mytimedelta, self).__div__(other)
        return _to_mydatetime(result)

    def __rmul__(self, other):
        result = super(mytimedelta, self).__rmul__(other)
        return _to_mydatetime(result)

    def __mul__(self, other):
        result = super(mytimedelta, self).__mul__(other)
        return _to_mydatetime(result)

1 个答案:

答案 0 :(得分:1)

嗯,这是正确的方法(我只是将转换器方法分成两部分)。 Python允许您减少代码重复:

from datetime import *

def convproxy(methods,converter):
    def f(cls):
        def _proxyfactory(method):
            def _convproxy(self,*args,**kwargs):
                return converter(getattr(super(cls,self),method)(*args,**kwargs))
            return _convproxy
        for m in methods:
            setattr(cls,m,_proxyfactory(m))
        return cls
    return f

@convproxy(('__add__','__sub__'),lambda d:mydatetime(d.timetuple()[:6]))
class mydatetime(datetime):
    pass

@convproxy(('__add__','__sub__','__div__','__rmul__','__mul__'),\
        lambda t:mytimetuple(t.days,t.seconds))
class mytimedelta(timedelta):
    pass

convproxy下的神秘代码只是在创建类时生成指定方法的智能方法,每个类都调用一个超类方法,并使用指定的转换函数从结果中创建一个子类。 / p>