子类 super returning self 应该 return 子类
Subclass super returning self should return subclass
我正在尝试扩展 datetime.date
class 允许添加 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__()
方法将 return datetime.date
的实例而不是 Date
.
根据我的理解,没有办法让 super().__add__()
知道 Date
类型。最优雅的解决方案是从 datetime.date
复制整个 __add__()
方法并添加我的额外代码。有没有办法在 Date.__add__()
方法中将 datetime.date
对象转换为 Date
对象?
这里是突出问题的片段:
D = Date(2000,1,1)
d = D + 1
type(d) # datetime.date instead of Date
编辑:我在查看 datetime.py(搜索 "class 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 中,并且根据 this post 对于这样的类型你不能分配给 __class__
。我有点困惑 datetime.py 中的代码是干什么用的。
The problem is that the add() method above will return an instance of datetime.date instead of a Date.
它会,但这就是您使用 super() 的原因,毕竟:您确实想要调用 super classes 的方法。
你可以只调用你自己的 class 的复制构造函数!
The most elegant solution is to copy the entire add() method from datetime.date and add my extra bit of code.
我认为这不能真正称为优雅的解决方案。另外,我认为 datetime 模块是 C.
添加后,只需从 datetime.date
和 return 创建另一个 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))
一般来说,super(Subclass, self).__add__(other)
可能returnSubclass
实例:
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__
方法被硬编码到 return datetime.date
个实例,即使对于 datetime.date
个子类也是如此。 In CPython, it is implemented in C 出于性能原因,不会从子类中调用(可能)纯 Python __add__
方法。纯 Python datetime.py
可能被其他 Python 实现使用,例如 Pypy、IronPython,Jython 不调用子类方法以与 CPython 兼容。
我正在尝试扩展 datetime.date
class 允许添加 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__()
方法将 return datetime.date
的实例而不是 Date
.
根据我的理解,没有办法让 super().__add__()
知道 Date
类型。最优雅的解决方案是从 datetime.date
复制整个 __add__()
方法并添加我的额外代码。有没有办法在 Date.__add__()
方法中将 datetime.date
对象转换为 Date
对象?
这里是突出问题的片段:
D = Date(2000,1,1)
d = D + 1
type(d) # datetime.date instead of Date
编辑:我在查看 datetime.py(搜索 "class 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 中,并且根据 this post 对于这样的类型你不能分配给 __class__
。我有点困惑 datetime.py 中的代码是干什么用的。
The problem is that the add() method above will return an instance of datetime.date instead of a Date.
它会,但这就是您使用 super() 的原因,毕竟:您确实想要调用 super classes 的方法。
你可以只调用你自己的 class 的复制构造函数!
The most elegant solution is to copy the entire add() method from datetime.date and add my extra bit of code.
我认为这不能真正称为优雅的解决方案。另外,我认为 datetime 模块是 C.
添加后,只需从 datetime.date
和 return 创建另一个 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))
一般来说,super(Subclass, self).__add__(other)
可能returnSubclass
实例:
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__
方法被硬编码到 return datetime.date
个实例,即使对于 datetime.date
个子类也是如此。 In CPython, it is implemented in C 出于性能原因,不会从子类中调用(可能)纯 Python __add__
方法。纯 Python datetime.py
可能被其他 Python 实现使用,例如 Pypy、IronPython,Jython 不调用子类方法以与 CPython 兼容。