我正在尝试扩展datetime.date
类,允许添加int
而不是使用timedelta
个对象:
class Date(datetime.date):
def __add__(self, other):
if isinstance(other, int):
other = datetime.timedelta(days=other)
return super(Date, self).__add__(other)
问题是上面的__add__()
方法会返回datetime.date
而不是Date
的实例。
根据我的理解,无法让super().__add__()
知道Date
类型。最优雅的解决方案是从__add__()
复制整个datetime.date
方法并添加我的额外代码。有没有办法在datetime.date
方法中将Date
对象转换为Date.__add__()
对象?
以下是一个突出显示问题的片段:
D = Date(2000,1,1)
d = D + 1
type(d) # datetime.date instead of Date
编辑:在查看datetime.py(搜索“课程日期”)后,我的第一个解决方案就是:
class Date(datetime.date):
def __add__(self, other):
if isinstance(other, int):
other = datetime.timedelta(days=other)
d = super(Date, self).__add__(other)
self.__year = d.year
self.__month = d.month
self.__day = d.day
return self # this is of type datetime.date
好吧,我想我会指出我的第一次尝试是这样的:
class Date(datetime.date):
def __add__(self, other):
if isinstance(other, int):
other = datetime.timedelta(days=other)
d = super(Date, self).__add__(other)
d.__class__ = Date
return d
这不起作用,因为(我怀疑)日期时间模块在C中,而根据this post,这些类型无法分配给__class__
。我对datetime.py中的代码有点困惑。
答案 0 :(得分:2)
添加后,只需从Date
创建另一个datetime.date
对象并按此返回
def __add__(self, other):
if isinstance(other, int):
other = datetime.timedelta(days=other)
result = super(Date, self).__add__(other)
return Date(result.year, result.month, result.day)
这是一个测试,
D = Date(2000, 1, 1) + 1
print(type(D), D)
# (<class '__main__.Date'>, Date(2000, 1, 2))
答案 1 :(得分:0)
问题是上面的add()方法将返回datetime.date的实例而不是Date。
它会,但这就是你为什么要使用super(),毕竟:你真的想打电话给超级班级&#39;方法。
你可以打电话给你自己的班级复制构造函数!
最优雅的解决方案是从datetime.date复制整个add()方法并添加我的额外代码。
我认为,这真的不能称之为优雅的解决方案。另外,我认为datetime模块是C。
答案 2 :(得分:0)
通常,super(Subclass, self).__add__(other)
可能会返回Subclass
个实例:
class Base(object):
__slots__ = 'n'
def __new__(cls, n):
self = object.__new__(cls)
self.n = n
return self
@classmethod
def fromordinal(cls, n):
return cls(n)
def __add__(self, other):
if hasattr(other, 'n'):
return self.fromordinal(self.n + other.n)
return NotImplemented
def __repr__(self):
return "{cls}({arg})".format(cls=self.__class__.__name__, arg=self.n)
def __eq__(self, other):
return self.n == other.n
class Subclass(Base):
__slots__ = ['_secret']
def __add__(self, other):
if hasattr(other, '_secret'):
other = self.fromordinal(other._secret)
return super(Subclass, self).__add__(other)
a = Subclass(1)
b = Subclass(2)
c = Subclass(2)
c._secret = 3
print(a + b)
print(a + c)
assert (a + b) == Subclass(3)
assert (a + c) == Subclass(4)
assert b == c and (a + b) != (a + c) and type(a + b) == type(a + c) == Subclass
但是datetime.date.__add__
方法被硬编码以返回datetime.date
个实例,即使对于datetime.date
子类也是如此。 In CPython, it is implemented in C出于性能原因,不会从子类调用(可能)纯Python __add__
方法。其他Python实现(如Pypy,IronPython,Jython)可能使用的纯Python datetime.py
不会调用子类方法来与CPython兼容。