Python 子类超级返回self应该返回子类
我正在尝试扩展Python 子类超级返回self应该返回子类,python,python-2.7,python-3.x,Python,Python 2.7,Python 3.x,我正在尝试扩展datetime.date类允许添加ints,而不是使用timedelta对象: class Date(datetime.date): def __add__(self, other): if isinstance(other, int): other = datetime.timedelta(days=other) return super(Date, self).__add__(other) 问题是上面的\uu
datetime.date
类允许添加int
s,而不是使用timedelta
对象:
class Date(datetime.date):
def __add__(self, other):
if isinstance(other, int):
other = datetime.timedelta(days=other)
return super(Date, self).__add__(other)
问题是上面的\uu add\uu()
方法将返回datetime.date
的实例,而不是date
根据我的理解,没有办法让super()。\uuuu add\uuuu()
知道Date
类型。最优雅的解决方案是从datetime.date
复制整个\uuuu add\uuu()
方法,并添加额外的代码位。是否有方法将datetime.date
对象强制转换为date
方法中的date
对象
下面是一个突出问题的片段:
D = Date(2000,1,1)
d = D + 1
type(d) # datetime.date instead of Date
编辑:查看(搜索“上课日期”)后,我的第一个解决方案是:
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
这将不起作用,因为(正如我所怀疑的)datetime模块是用C编写的,并且根据这些类型,您不能将其分配给\uuuuuu class\uuuu
。我有点困惑datetime.py中的代码是什么
问题是上面的add()方法将返回datetime.date的实例,而不是日期
它会的,但这就是为什么您要使用super(),毕竟:您确实想要调用super类的方法
您可以调用自己类的复制构造函数
最优雅的解决方案是从datetime.date复制整个add()方法,并添加额外的代码
我认为这不是一个很好的解决方案。另外,我认为datetime模块是C。添加后,只需从
datetime.Date
创建另一个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))
D=日期(2000,1,1)+1
打印(类型(D),D)
#(,日期(2000年1月2日))
一般来说,super(Subclass,self)。\uu添加(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.\uu添加
方法被硬编码为返回datetime.date
实例,即使对于datetime.date
子类也是如此。出于性能原因,不从子类调用(可能)纯Python\uuuuuuuuuuuuuuuuuuuuuuuuuuu
方法。其他Python实现(如Pypy、IronPython、Jython)可能使用的纯Pythondatetime.py
,不调用子类方法以与CPython兼容。类似于返回日期(super(Date,self)的东西怎么样不幸的是,
?@bimsapi不起作用。似乎datetime.date
的构造函数不是那么好。当然super
方法返回一个datetime.date
,这是超类!你可以从中创建一个date
,d=super(date,self)。\uu添加(other);返回日期(d.year,d.month,d.day)
。是的,它是C。有一个datetime.py
,但是所有的方法都是空的,并且不返回任何值。好的,我认为是C可以解释为什么我不能只覆盖self。uuu class\uuu=Date in Date。uuu在返回对象之前添加。\uu()第一个更改似乎不需要。@matsjoyce哦,是的。这是不必要的。谢谢:)是的,工作-这是我上面第一次编辑的优雅版本:)@s5s实际上,您的编辑使+
成为一个可变操作,这是不推荐的。那么datetime.py文件做什么呢?这仅仅是围绕C代码的python包装吗?@s5s:请参阅python发行版7989::stdlib的长期目标是将C扩展模块最小化,使其仅限于那些必须用C编写的模块(模块仍然可以具有增强性能的扩展后端)。由于datetime不满足这一要求,因此datetime将获得纯Python版本,并且仅为提高性能而使用扩展代码,这不是“如果”的问题,而是“何时”的问题。。。要记住的关键是,这是为了使除CPython之外的vm不被视为二级。