为什么我不能将datetime.date子类化?

Ark*_*ady 19 python oop datetime subclass

以下为什么不工作(Python 2.5.2)?

>>> import datetime
>>> class D(datetime.date):
        def __init__(self, year):
            datetime.date.__init__(self, year, 1, 1)
>>> D(2008)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: function takes exactly 3 arguments (1 given)
Run Code Online (Sandbox Code Playgroud)

我想创建一个类似datetime.date但具有不同__init__功能的类.显然我的功能永远不会被调用.相反,原来datetime.date.__init__被调用并失败,因为这需要3个参数,而我正在传递一个.

这里发生了什么?这是一个线索吗?

>>> datetime.date.__init__
<slot wrapper '__init__' of 'object' objects>
Run Code Online (Sandbox Code Playgroud)

谢谢!

A. *_*ady 36

关于其他几个答案,这与用C本身实现的日期没有任何关系.该__init__方法无效,因为它们是不可变对象,因此构造函数(__new__)应该完成所有工作.您会看到子类化int,str等的相同行为.

>>> import datetime
>>> class D(datetime.date):
        def __new__(cls, year):
            return datetime.date.__new__(cls, year, 1, 1)


>>> D(2008)
D(2008, 1, 1)
Run Code Online (Sandbox Code Playgroud)


tzo*_*zot 10

请阅读关于数据模型的Python参考,特别是有关__new__ 特殊方法的参考.

摘录自该页面(我的斜体):

__new__()主要用于允许不可变类型的子类(如int,str或tuple)自定义实例创建.它也通常在自定义元类中重写,以自定义类创建.

datetime.datetime 也是一种不可变的类型.

PS如果您认为:

  • 用C实现的对象不能被子类化,或者
  • __init__ 不会仅为C实现的对象调用 __new__

那请试试吧:

>>> import array
>>> array
<module 'array' (built-in)>
>>> class A(array.array):
    def __init__(self, *args):
        super(array.array, self).__init__(*args)
        print "init is fine for objects implemented in C"

>>> a=A('c')
init is fine for objects implemented in C
>>> 
Run Code Online (Sandbox Code Playgroud)