Почему я не могу подклассифицировать 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>
Спасибо!
Ответы
Ответ 1
Что касается нескольких других ответов, это не имеет ничего общего с датами, внедряемыми в C per se. Метод __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)
Ответ 2
Пожалуйста, прочитайте ссылку Python на Модель данных, особенно о __new__
специальный метод.
Выдержка из этой страницы (курсив мой):
__new__()
предназначен главным образом для того, чтобы позволить подклассам неизменяемых типов (например, int, str или кортеж) настраивать создание экземпляра. Он также обычно переопределяется в пользовательских метаклассах, чтобы настроить создание классов.
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
>>>
Ответ 3
Здесь ответ и возможное решение (используйте функцию или strptime вместо подкласса)
http://www.mail-archive.com/[email protected]/msg192783.html
Ответ 4
Функция вы не обходитесь; Python просто никогда не доходит до точки, где он будет ее называть. Поскольку datetime реализуется в C, он выполняет свою инициализацию в datetime.__new__
not datetime.__init__
. Это связано с тем, что datetime является неизменным. Вероятно, вы можете обойти это, переопределив __new__
вместо __init__
. Но, как предложили другие люди, лучший способ - это, вероятно, вообще не подклассы datetime.
Ответ 5
Вероятно, вы должны использовать функцию factory вместо создания подкласса:
def first_day_of_the_year(year):
return datetime.date(year, 1, 1)
Ответ 6
Вы можете обернуть его и добавить расширенную функциональность в свою упаковку.
Вот пример:
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
.