为什么第二次不调用构造函数?

Why isn't the constructor called the second time?

为什么第二次没有调用构造函数?

from datetime import datetime

class Time(datetime):
    def __init__(self, *args):
        print 5, args
        try:
            d = args[0]
            print 8, d
            datetime.__init__(self,
                d.year, d.month, t.day, t.hour, t.minute, t.second)
        except Exception:
            print 12, args
            datetime.__init__(self, args)

if __name__ == '__main__':
    t = Time(1965, 1, 10)
    print 17, t
    u = Time(t)
    print 19, u

使用 python 2.7.2,输出如下:

bash-4.1$ python tmp.py
5 (1965, 1, 10)
8 1965
12 (1965, 1, 10)
17 1965-01-10 00:00:00
Traceback (most recent call last):
  File "tmp.py", line 18, in <module>
    u = Time(t)
TypeError: an integer is required

我希望看到:

5 Time(1965, 1, 10)

如果不是构造函数,调用的是什么函数?

这是类型的 __new__ 方法。

__init__ 并不是创建对象时发生的第一件事。首先调用类型的__new__方法实际产生对象,然后调用__init__进行初始化。对于可变类型,__new__ 通常不会做太多,但对于像 datetime 这样的不可变类型,__new__ 通常会创建预初始化的对象,否则 __init__ 将不得不改变对象以初始化它。

如果你想继承datetime,你必须实现__new__以及__init__:

def __new__(cls, *args):
    print 5, args
    try:
        d = args[0]
        print 8, d
        return datetime.__new__(cls,
            d.year, d.month, t.day, t.hour, t.minute, t.second)
    except Exception:
        print 12, args
        return datetime.__new__(cls, args)

如果您想查看 datetime__new__ 的作用,可以在 Modules/datetimemodule.c 中看到。不过,您必须了解 C 并了解或查找一堆 Python C-api 内容才能理解它。