覆盖运算符+;制定日期+;时间=Python中的日期时间

覆盖运算符+;制定日期+;时间=Python中的日期时间,python,operator-overloading,Python,Operator Overloading,我有几节课在延长内置日期时间* 有没有什么好的理由不重载+(MyTime.\uuud\uuuud\uuuuuu)所以MyDate+MyTime返回一个MyDateTime?这通常会被反对,因为你实际上是在合并而不是添加;这就是为什么实际的datetime库有一个方法,而不是以这种方式使用加法 我不知道Python中有任何其他情况下,+会产生。因此,建议您只需提供一个combine方法,而不是重载添加。这已经作为类方法实现了: 印刷品 2010-12-05 10:22:15 是的,至少有一个理由

我有几节课在延长内置日期时间*


有没有什么好的理由不重载+(
MyTime.\uuud\uuuud\uuuuuu
)所以MyDate+MyTime返回一个MyDateTime?

这通常会被反对,因为你实际上是在合并而不是添加;这就是为什么实际的datetime库有一个方法,而不是以这种方式使用加法


我不知道Python中有任何其他情况下,
+
会产生
。因此,建议您只需提供一个
combine
方法,而不是重载添加。

这已经作为类方法实现了:

印刷品

2010-12-05 10:22:15

是的,至少有一个理由不这样做:结果实例与两个输入实例完全不同。这重要吗?我不这么认为——考虑<代码>日期-日期<代码>收益>代码>时间增量< /COD> < /P> 在我看来:

  • 把两个日期加在一起有意义吗?没有
  • 两次相加有意义吗?没有
  • 把日期和时间加在一起有意义吗?是的
  • 将日期和时间差添加到一起有意义吗?也许吧
  • 将时间和时间差相加有意义吗?也许吧
减法呢

  • 减去两个日期有意义吗?对
  • 减法两次有意义吗?对
  • 从日期中减去时间有意义吗?没有
  • 从日期中减去时间差有意义吗?也许吧
  • 从时间中减去时间增量有意义吗?也许吧
按照合理的思路发展:

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
date - date
time - time
datetime + timedelta
datetime - timedelta
对于这些:

date +/- timedelta
time +/- timedelta

如果timedelta没有其他类型,我会默认返回相同的类型,如果timedelta确实有其他类型,则会引发异常,但会有一个设置来控制它。另一种可能的行为是删除不需要的部分——因此,如果日期与具有小时数的timedelta相结合,则会删除小时数并返回日期。

我想最重要的是功能和效率。当然,使用一个简单的
+
操作符会更容易使用,但我不确定它的功能

如果我们将其与
datetime.combine
进行比较,
combine
所做的是:

dt = date(2011,01,01)
tm = time(20,00)
dtm = datetime.combine(dt, tm)
对于dtm

  • 如果
    dt
    是日期对象而
    tm
    是时间对象,则日期信息取自
    dt
    ,时间信息和tzinfo取自
    tm
    对象
  • 如果
    dt
    是datetime对象,则其时间和tzinfo属性将被忽略
从这个角度来看,使用
datetime
对象似乎不是简单的对象,而是更复杂的具有不同属性的结构,如时区信息

这可能就是为什么
datetime
对象具有一些附加函数,用于格式化对象类型和对象的数据结构

Python有一个座右铭(类似于此):

在python中,没有什么是不可更改的,如果您知道自己在做什么。如果不是,最好保持库函数的原样


因此,在我看来,最好使用
combine
,重载
+
运算符

由于存在日期、时间和日期时间交叉类型的加减运算符,我认为这是可以的,只要定义良好

目前(2.7.2):

我认为以下情况也适用于延期:

timedelta = time - time
datetime = date + time
我还打算提出以下建议,但是
时间
对于
小时
分钟
、和
微秒
,有非常具体的最小值和最大值,因此需要对值进行无声环绕或返回不同的类型:

time = time + timedelta
time = time - timedelta
类似地,
date
无法处理添加的
timedelta
少于一天的数据。经常有人告诉我,只需使用Python的Duck类型,因为这就是目的所在如果这是真的,那么我将提出以下完整的界面:

[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]
不太满意。从并行性和精确性的角度考虑界面的其余部分是有意义的,但我确实认为将时间概括为适当的时间可能更为优雅,从而将所有的
[time | timedelta]
更改为简单的
时间
,但不幸的是,这让我们失去了精确性

在我看来,运算符重载最有价值的用途是可以组合许多输入值的情况。你永远不会想处理:

concat(concat(concat("Hello", ", "), concat("World", "!")), '\n');

因此,我们重载数学符号以创建更直观的语法。处理这个问题的另一种方法是可变函数,如Scheme中的
+

对于您的
date+time=datetime
,添加
datetime+datetime
datetime+time
datetime+date
是没有意义的,因此您永远不会遇到上述情况

在我看来,再次强调,正确的做法是使用构造函数方法。在C++这样的强类型的语言中,你将拥有<代码>日期时间(const Dead and d,const Time&t)。对于Python的动态类型,我想他们给了函数一个名称,
dat
[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
concat(concat(concat("Hello", ", "), concat("World", "!")), '\n');
distance = sqrt(add(add(x*x, y*y), z*z));