子类化日期时间:是否有更好的方法在算术运算后维护结果对象类型?

发布于 2024-12-18 14:37:24 字数 1576 浏览 0 评论 0原文

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

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)

I recently ran into a situatiton where I needed to subclass datetime.datetime and datetime.timedelta in order to add a few methods. I immediately found, though, that any arithmetic operations would return a datetime.datetime object when I expected it to return a mydatetime.mydatetime instance instead. Below is the solution that a co-worker helped me out with for this problem. Does anyone have a more concise or convenient suggestion? Are there any dangers to what I have done here? Am I missing anything important?

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

变身佩奇 2024-12-25 14:37:24

嗯,这是正确的方法(我只是将转换器方法分成两个)。不过,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 下的神秘代码只是在创建类时生成指定方法的一种聪明方法,每个方法都调用一个超类方法并从中创建一个子类使用指定转换器函数的结果。

Well, this is the right way to do it (i'd just split the converter method into two). Python allows you to reduce code duplication though:

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

The cryptic code under convproxy is just a smart-aleck way to generate the specified methods when creating a class, each of which calls a superclass method and creates a subclass from the result using the specified converter function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文