为什么不能继承datetime.date?

问题描述 投票:19回答:6

为什么以下功能不起作用(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)

我想创建一个类似于datetime.date的类,但具有不同的__init__函数。显然我的函数永远不会被调用。相反,原始的datetime.date.__init__被调用并失败,因为它需要3个参数,而我要传递一个。

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

>>> datetime.date.__init__
<slot wrapper '__init__' of 'object' objects>

谢谢!

python oop datetime subclass
6个回答
36
投票
关于其他几个答案,这与用C本身实现的日期无关。 __init__方法不执行任何操作,因为它们是

immutable对象,因此构造函数(__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)

11
投票
请阅读Data model上的Python参考,尤其是有关__new__ special method的内容。

该页节录(斜体):

__new__()主要目的是允许

immutable类型的子类(例如int,str或tuple)成为customize instance creation。为了自定义类的创建,它通常也被自定义元类覆盖。

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 >>>


  • 4
    投票
    这是答案,以及可能的解决方案(使用函数或strptime代替子类)

    http://www.mail-archive.com/[email protected]/msg192783.html


    2
    投票
    您的功能不会被忽略; Python永远都不会达到调用它的地步。由于datetime是在C中实现的,因此它将在datetime.__new__中而不是在datetime.__init__中进行初始化。这是因为datetime是不可变的。您可以通过覆盖__new__而不是__init__来解决此问题。但是,正如其他人所建议的那样,最好的方法可能是根本不继承日期时间。

    0
    投票
    您可能应该使用工厂函数而不是创建子类:

    def first_day_of_the_year(year): return datetime.date(year, 1, 1)


    0
    投票
    您可以

    包装,并将扩展功能添加到包装器。

    这里是一个例子:

    class D2(object): def __init__(self, *args, **kwargs): self.date_object = datetime.date(*args, **kwargs) def __getattr__(self, name): return getattr(self.date_object, name)

    这是它的工作方式:

    >>> d = D2(2005, 10, 20) >>> d.weekday() 3 >>> dir(d) ['__class__', '__delattr__', '__dict__', '__doc__', '__getattr__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'date_object'] >>> d.strftime('%d.%m.%Y') '20.10.2005' >>>

    请注意,dir()未列出datetime.date的属性。
    © www.soinside.com 2019 - 2024. All rights reserved.