繁体   English   中英

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

[英]Why can't I subclass datetime.date?

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

谢谢!

关于其他几个答案,这与用 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)

请阅读关于数据模型的 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
>>> 

这是答案和可能的解决方案(使用函数或 strptime 而不是子类化)

http://www.mail-archive.com/python-list@python.org/msg192783.html

你的功能没有被绕过; Python 永远不会到达调用它的地步。 由于 datetime 是在 C 中实现的,因此它在datetime.__new__而不是datetime.__init__ 这是因为日期时间是不可变的。 您大概可以通过覆盖__new__而不是__init__来解决这个问题。 但正如其他人所建议的那样,最好的方法可能根本不是对日期时间进行子类化。

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

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

您可以包装它并向您的包装器添加扩展功能。

下面是一个例子:

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的属性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM