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

发布于 2024-07-11 03:17:51 字数 679 浏览 2 评论 0原文

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

谢谢!

Why doesn't the following work (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)

I wanted to create a class that was just like datetime.date, but with a different __init__ function. Apparently my function never gets called. Instead the original datetime.date.__init__ is called and fails because that expects 3 arguments and I am passing in one.

What's going on here? And is this a clue?

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

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

薄情伤 2024-07-18 03:17:51

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

Regarding several other answers, this doesn't have anything to do with dates being implemented in C per se. The __init__ method does nothing because they are immutable objects, therefore the constructor (__new__) should do all the work. You would see the same behavior subclassing int, str, etc.

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


>>> D(2008)
D(2008, 1, 1)
绿光 2024-07-18 03:17:51

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

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

__new__() 主要旨在允许不可变类型(如 int、str 或 tuple)的子类自定义实例创建。 为了自定义类创建,它通常也会在自定义元类中被重写。

datetime.datetime 也是一个不可变类型。

PS 如果您认为:

  • 用 C 实现的对象不能被子类化,或者
  • C 实现的对象不会调用 __init__ ,只有 __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
>>> 

Please read the Python reference on Data model, especially about the __new__ special method.

Excerpt from that page (my italics):

__new__() is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation.

datetime.datetime is also an immutable type.

PS If you think that:

  • an object implemented in C cannot be subclassed, or
  • __init__ doesn't get called for C implemented objects, only __new__

then please try it:

>>> 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
>>> 
云雾 2024-07-18 03:17:51

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

http://www.mail-archive.com/[电子邮件受保护]/msg192783.html

Here's the answer, and a possible solution (use a function or strptime instead of subclassing)

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

海未深 2024-07-18 03:17:51

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

You're function isn't being bypassed; Python just never gets to the point where it would call it. Since datetime is implemented in C, it does its initialization in datetime.__new__ not datetime.__init__. This is because datetime is immutable. You could presumably get around this by overriding __new__ instead of __init__. But as other people have suggested, the best way is probably not subclassing datetime at all.

失而复得 2024-07-18 03:17:51

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

下面是一个示例:

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

You can wrap it and add extended functionality to your wrapper.

Here is an example:

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)

And here is how it works:

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

Note that dir() doesn't list datetime.dates attributes.

落墨 2024-07-18 03:17:51

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

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

You should probably use a factory function instead of creating a subclass:

def first_day_of_the_year(year):
  return datetime.date(year, 1, 1)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文