Author belopolsky
Recipients amaury.forgeotdarc, belopolsky, mark.dickinson, stingray
Date 2010-06-09.18:51:05
SpamBayes Score 0.0
Marked as misclassified No
Message-id <>
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 
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>.

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.
Date User Action Args
2010-06-17 20:24:08brett.cannonsetspambayes_score: 9.15026e-06 -> 0.0
2010-06-09 18:51:08belopolskysetrecipients: + belopolsky, amaury.forgeotdarc, mark.dickinson, stingray
2010-06-09 18:51:08belopolskysetmessageid: <>
2010-06-09 18:51:06belopolskylinkissue2267 messages
2010-06-09 18:51:05belopolskycreate