我有几个类扩展内置日期时间。*
有没有充分理由不重载+(MyTime.__radd___
)所以MyDate + MyTime会返回MyDateTime?
答案 0 :(得分:16)
这已经作为类方法实现,datetime.datetime.combine
:
import datetime
d = datetime.date(2010, 12, 5)
t = datetime.time(10, 22, 15)
dt = datetime.datetime.combine(d, t)
print dt
打印
2010-12-05 10:22:15
答案 1 :(得分:12)
这通常是不赞成的,因为你真的是在结合而不是加入;这就是为什么实际的日期时间库有一个combine方法而不是以这种方式使用添加。
我不知道Python中<instance of TypeA> + <instance of TypeB>
产生<instance of TypeC>
的任何其他情况。因此,Principle of least astonishment表示您应该只提供combine
方法而不是重载添加。
答案 2 :(得分:4)
是的,至少有一个很好的理由不:结果实例与两个输入实例完全不同。这很重要吗?我不这么认为 - 考虑date - date
会产生timedelta
。
我看待它的方式:
和减法
沿着有意义的路线发展:
date + time => datetime
date + timedelta => date | datetime or exception or silently drop time portion
time + date => datetime
time + timedelta => time | wrap-around or exception
date - date => timedelta
date - timedelta => date | datetime or exception or silently drop time portion
time - time => timedelta
time - timedelta => time | wrap-around or exception
datetime + timedelta => datetime
datetime - timedelta => datetime
所以,如果是我和我正在设计Date,Time,DateTime,TimeDelta框架,我会允许:
date + time
date - date
time - time
datetime + timedelta
datetime - timedelta
并为这些:
date +/- timedelta
time +/- timedelta
如果timedelta没有其他类型,我会默认返回相同的类型,如果timedelta确实有其他类型的某些类型,则会引发异常,但会有一个设置可以控制它。另一种可能的行为是删除不需要的部分 - 所以一个日期与一个有时间的timedelta相结合会减少时间并返回一个日期。
答案 3 :(得分:1)
由于日期,时间和日期时间存在交叉类型的加法和减法运算符,我认为这很好,只要它定义得很好。
目前(2.7.2):
date = date + timedelta
date = date - timedelta
timedelta = date - date
datetime = datetime + timedelta
datetime = datetime - timedelta
timedelta = datetime - datetime
我认为以下内容对于扩展也是合理的:
timedelta = time - time
datetime = date + time
我也会建议以下内容,但time
具有hour
,minute
,second
和{{1}的非常具体的最小值和最大值因此,需要静默环绕值或返回不同类型:
microsecond
同样地,time = time + timedelta
time = time - timedelta
无法处理添加到其中的不到一天的date
。通常我被告知只需使用Duck打字与Python ,因为这是意图。 如果确实如此,那么我建议使用以下完整的界面:
timedelta
其中,考虑到[date|datetime] = date + timedelta
[date|datetime] = date - timedelta
timedelta = date - date
[time|timedelta] = time + timedelta
[time|timedelta] = time - timedelta
timedelta = time - time
datetime = datetime + timedelta
datetime = datetime - timedelta
datetime = date + time
datetime = date - time
timedelta = datetime - datetime
timedelta = datetime - date
timedelta = timedelta + timedelta
timedelta = timedelta - timedelta
具有精确损失的情况(对于部分天数为date
),它将被提升为timedelta
。同样地,鉴于datetime
具有精确度损失的情况(对于产生超过一天或负时间的结果的time
),它将被提升为timedelta
。 然而,我对timedelta
感到不舒服。考虑到并行性和精确视图的其余界面,它是有意义的,但我认为将时间环绕到正确的小时可能更优雅,从而将所有[time|timedelta]
更改为简单{{1但遗憾的是,这让我们失去了精确度。
答案 4 :(得分:1)
在我看来,运算符重载的最有价值的用途是可以组合许多输入值的情况。你永远不想处理:
concat(concat(concat("Hello", ", "), concat("World", "!")), '\n');
或
distance = sqrt(add(add(x*x, y*y), z*z));
因此我们重载数学符号以创建更直观的语法。处理此问题的另一种方法是可变函数,例如Scheme中的+
。
使用date + time = datetime
,添加datetime + datetime
,datetime + time
或datetime + date
没有任何意义,因此您永远不会遇到上述情况。< / p>
在我看来,正确的方法是使用构造函数方法。在像C ++这样强类型的语言中,你有DateTime(const Date &d, const Time &t)
。使用Python的动态类型,我猜他们给函数命名datetime.combine(date, time)
,以便在代码中看不到输入变量的类型时使代码更清晰。
答案 5 :(得分:0)
我猜最重要的是功能和效率。当然使用简单的+
运算符会更容易使用,但我不确定功能。
如果我们将其与datetime.combine
进行比较,那么combine
做的是:
dt = date(2011,01,01)
tm = time(20,00)
dtm = datetime.combine(dt, tm)
dtm
dt
是日期对象且tm
是时间对象,则 date 信息取自dt
,时间 info和 tzinfo 取自tm
对象dt
是 datetime 对象,则 time 和 tzinfo 属性将被忽略。从这个角度来看,使用datetime
对象似乎不是简单的对象,而是具有不同属性的更复杂结构,例如时区信息。
可能这就是为什么datetime
个对象有一些额外的函数用于格式化对象的对象类型和数据结构。
Python有一个座右铭(类似的东西):
在python中,没有任何东西是不可改变的,如果你知道自己在做什么。如果没有,最好保留库函数......
因此,在我看来,最好使用combine
重载+
运算符