[issue2267] datetime.datetime operator methods are not subclass-friendly

Alexander Belopolsky report at bugs.python.org
Wed Jun 9 20:51:08 CEST 2010


Alexander Belopolsky <belopolsky at users.sourceforge.net> added the comment:

I would like to take another shot at this. The link in Amaury's closing comment no longer works, so here is the relevant post:

"""
Returning same type as self for arithmetic in subclasses

Tim Peters tim.peters at gmail.com 
Sat Jan 8 02:09:27 CET 2005

[Max M]
> """
> I subclass datetime and timedelta
> 
> >>> dt = myDatetime(1970,1,1)
> >>> type(dt)
> <class 'dtime.myDatetime'>
> 
> >>> td = myTimedelta(hours=1)
> >>> type(td)
> <class 'dtime.myTimedelta'>
> 
> But when I do arithmetic with these classes, they return datetime and
> timedelta,
...
> >>> new_time = dt + td
> >>> new_time
> datetime.datetime(1970, 1, 1, 1, 0)
> 
> >>> type(new_time)
> <type 'datetime.datetime'>

Yes, and all builtin Python types work that way.  For example,
int.__add__ or float.__add__ applied to a subclass of int or float
will return an int or float; similarly for a subclass of str.  This
was Guido's decision, based on that an implementation of any method in
a base class has no idea what requirements may exist for invoking a
subclass's constructor.  For example, a subclass may restrict the
values of constructor arguments, or require more arguments than a base
class constructor; it may permute the order of positional arguments in
the base class constructor; it may even be "a feature" that a subclass
constructor gives a different meaning to an argument it shares with
the base class constructor.  Since there isn't a way to guess, Python
does a safe thing instead.

> where I want them to return myDatetime and myTimedelta
>
> So I wondered if there was a simlpler way to coerce the result into my
> desired types rather than overwriting the __add__, __sub__ etc. methods?

Generally speaking, no.  But I'm sure someone will torture you with a
framework that purports to make it easy <wink>.
"""  http://mail.python.org/pipermail/python-list/2005-January/925838.html


As I explained in my previous post, the same argument, "base class has no idea what requirements may exist for invoking a subclass's constructor", applies to class methods, but they nevertheless consistently construct subclass instances:

>>> class d(datetime): pass
>>> d.utcfromtimestamp(0)
d(1970, 1, 1, 0, 0)
>>> d.fromtimestamp(0)
d(1969, 12, 31, 19, 0)
>>> d.combine(date(1,1,1), time(1,1))
d(1, 1, 1, 1, 1)


Similar example for the date class:

>>> class Date(date): pass
>>> Date.fromordinal(1)
Date(1, 1, 1)


In my view it is hard to justify that for a Date instance d, and integer days, Date.fromordinal(d.toordinal() + days) happily produces a Date instance, but d + timedelta(days) returns a basic date instance.

----------
assignee:  -> belopolsky
components: +Extension Modules -Library (Lib)
nosy: +mark.dickinson
resolution: wont fix -> 
status: closed -> open
versions: +Python 3.2 -Python 2.5

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue2267>
_______________________________________


More information about the Python-bugs-list mailing list