为方便起见,我想创建datetime.timedelta的子类。我们的想法是定义一个类:
class Hours(datetime.timedelta):
def __init__(self, hours):
super(Hours, self).__init__(hours=hours)
所以我可以快速创建这样的timedeltas:
x = Hours(n)
但是,上面的代码产生n天而不是n小时的时间值。举个例子,看看下面的ipython会话:
In [1]: import datetime
In [2]: class Hours(datetime.timedelta):
...: def __init__(self, hours):
...: super(Hours, self).__init__(hours=hours)
...:
In [3]: print(Hours(10))
Out[3]: 10 days, 0:00:00
我无法解释这一点。有人吗?
答案 0 :(得分:12)
如果您使用__new__
,而不是__init__
:
import datetime as DT
class Hours(DT.timedelta):
def __new__(self, hours):
return DT.timedelta.__new__(self, hours=hours)
x = Hours(10)
print(x)
产量
10:00:00
如果您覆盖__init__
,而不是__new__
,那么DT.timedelta.__new__
会在 Hours.__init__
之前被称为。注意
import datetime as DT
class Hours(DT.timedelta):
def __init__(self, hours):
print(self)
x = Hours(10)
打印10 days, 0:00:00
。这表明DT.timedelta.__new__
已经将timedelta设置为10天,然后才有机会在Hours.__init__
中配置它。
此外,DT.timedelta
是一个不可变对象 - 在实例化对象后,您无法更改days
或seconds
或microseconds
。 Python使用__new__
方法创建不可变对象,通常不会在__init__
方法中执行任何操作。可变对象反过来:它们在__init__
中配置对象,而在__new__
中不执行任何操作。
每the docs:
当继承不可变的内置类型(如数字和字符串)时, 偶尔在其他情况下,静态方法
__new__
会出现 派上用场。__new__
是实例构造的第一步,被调用 在__init__
之前。以类为其调用__new__
方法 第一个论点;它的责任是返回一个新的实例 类。将其与__init__
进行比较:使用实例调用__init__
作为它的第一个论点,它不返回任何东西;它的 责任是初始化实例....所有这一切都是为了使不可变类型可以保留它们 允许子类化的不变性。
(如果不可变对象在__init__
中执行配置,那么你可以通过调用immutable.__init__
来改变不可变。显然,我们不希望这样,所以immutable.__init__
通常什么也不做。)
另请注意,除非您计划向Hours
类添加新方法,否则它会更简单,因此更好地使用函数:
def hours(hours):
return DT.timedelta(hours=hours)