【问题标题】:How to extend datetime.timedelta?如何扩展 datetime.timedelta?
【发布时间】:2020-05-11 15:53:30
【问题描述】:

我正在尝试扩展 Python datetime.timedelta 以用于越野比赛结果。我想从格式为u"mm:ss.s" 的字符串构造一个对象。我可以使用工厂设计模式和@classmethod 注释来实现这一点。我将如何通过覆盖__init__ 和/或__new__ 来完成同样的任务?

使用下面的代码,构造对象会引发 TypeError。注意__init__ 没有被调用,因为'in my __init__' 没有被打印出来。

import datetime
import re

class RaceTimedelta(datetime.timedelta):
    def __init__(self, timestr = ''):
        print 'in my __init__'
        m = re.match(r'(\d+):(\d+\.\d+)', timestr)
        if m:
            mins = int(m.group(1))
            secs = float(m.group(2))
            super(RaceTimedelta, self).__init__(minutes = mins, seconds = secs)
        else:
            raise ValueError('timestr not in format u"mm:ss.d"')

这是错误:

>>> from mytimedelta import RaceTimedelta
>>> RaceTimedelta(u'24:45.7')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported type for timedelta days component: unicode
>>> 

如果我将代码从 __init__ 移动到 __new__,我会得到以下信息。注意这一次,输出显示我的__new__函数被调用了。

>>> RaceTimedelta(u'24:45.7')
in my __new__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "mytimedelta.py", line 16, in __new__
    super(RaceTimedelta, self).__new__(minutes = mins, seconds = secs)
TypeError: datetime.timedelta.__new__(): not enough arguments
>>> 

【问题讨论】:

  • datetime是用C实现的。如果你只想替换构造函数,只要有一个方便的函数来解析字符串会容易得多。
  • 感谢您的建议。最终目标是在比赛结果表中显示时间。出于这个原因,我还想覆盖__str__,以便更轻松地使用漂亮的打印机模块。

标签: python datetime


【解决方案1】:

显然timedelta 对象是不可变的,这意味着它们的值实际上是在类的__new__() 方法中设置的——因此您需要覆盖该方法而不是它的__init__():

import datetime
import re

class RaceTimedelta(datetime.timedelta):
    def __new__(cls, timestr=''):
        m = re.match(r'(\d+):(\d+\.\d+)', timestr)
        if m:
            mins, secs = int(m.group(1)), float(m.group(2))
            return super(RaceTimedelta, cls).__new__(cls, minutes=mins, seconds=secs)
        else:
            raise ValueError('timestr argument not in format "mm:ss.d"')

print RaceTimedelta(u'24:45.7')

输出:

0:24:45.700000

顺便说一句,我觉得很奇怪您为timestrkeyword 参数提供了一个默认值,该参数将被视为非法并引发ValueError。

【讨论】:

  • 默认值无效的想法是在RaceTimedelta()的情况下提供更友好的错误消息。
  • 我明白了。也许将其更改为 def __new__(cls, timestr='no default'): 或添加评论会使事情更清楚(对于阅读代码的其他人)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-22
  • 2018-08-22
  • 2011-06-09
  • 2010-10-09
  • 2014-01-28
  • 2016-09-25
相关资源
最近更新 更多