为什么以下工作不起作用(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>
谢谢!
答案 0 :(得分:35)
关于其他几个答案,这与用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)
答案 1 :(得分:10)
请阅读Data model上的Python参考资料,尤其是__new__
special method。
摘录自该页面(我的斜体):
__new__()
主要用于允许不可变类型的子类(如int,str或tuple)来自定义实例创建。它也通常在自定义元类中重写,以自定义类创建。
datetime.datetime
也是一种不可变类型。
PS如果您认为:
__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
>>>
答案 2 :(得分:4)
这是答案,可能的解决方案(使用函数或strptime而不是子类)
http://www.mail-archive.com/python-list@python.org/msg192783.html
答案 3 :(得分:2)
你的功能并没有被绕过; Python永远不会达到它所称的地步。由于datetime在C中实现,因此它在datetime.__new__
而不是datetime.__init__
中进行初始化。这是因为datetime是不可变的。你可以通过覆盖__new__
代替__init__
来解决这个问题。但正如其他人所建议的那样,最好的方法可能根本就不是继承日期时间。
答案 4 :(得分:0)
您应该使用工厂函数而不是创建子类:
def first_day_of_the_year(year):
return datetime.date(year, 1, 1)
答案 5 :(得分: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
的属性。