This issue tracker has been migrated to GitHub ,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2008年03月10日 19:09 by stingray, last changed 2022年04月11日 14:56 by admin. This issue is now closed.
| Files | ||||
|---|---|---|---|---|
| File name | Uploaded | Description | Edit | |
| datetime.diff | belopolsky, 2008年03月10日 22:05 | patch against revision 61343 | review | |
| Messages (14) | |||
|---|---|---|---|
| msg63446 - (view) | Author: Paul Komkoff (stingray) | Date: 2008年03月10日 19:09 | |
The datetime.datetime class overrides some arithmetic operations for it to be able to add or subtract timedeltas. However, the result of A + B operation, where A is instance of a subclass of datetime and B is timedelta instance will be always the instance of base datetime. This is extremely annoying and requires to override arithmetic operators and writing a lots of rubbish to replace the datetime base object with type(self) |
|||
| msg63452 - (view) | Author: Alexander Belopolsky (belopolsky) * (Python committer) | Date: 2008年03月10日 22:05 | |
This is trivial to implement (see attached) and IMHO is a good idea. The next question, however is whether similar changes should be made to timedelta arithmetics. Timedelta case is not so clearcut because of the usual dilemma of what the type of a+b should be when a and b are instances of two different subclasses of timedelta. |
|||
| msg63453 - (view) | Author: Paul Komkoff (stingray) | Date: 2008年03月10日 22:21 | |
I just checked the astimezone method - it also does this. As with timedelta... well, it's not critical for me now but it worth thinking about :) |
|||
| msg63454 - (view) | Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) | Date: 2008年03月10日 23:05 | |
Recently, the similar issue1562 "Decimal can't be subclassed useful" was rejected. In the discussion I found a reference to a former post, which precisely deals with datetime and timedelta: http://mail.python.org/pipermail/python-list/2005-January/300791.html The main argument is that the """base class has no idea what requirements may exist for invoking a subclass's constructor""" All python types behave this way: int, float, lists. |
|||
| msg63456 - (view) | Author: Alexander Belopolsky (belopolsky) * (Python committer) | Date: 2008年03月11日 00:29 | |
Invoking a subclass's constructor is only an issue when subclass adds
data members. In this case, arithmetic methods need to be overridden.
Note that my patch does not make __add__ and friends invoke subclass'
constructor, only subclass' tp_alloc.
Existing code already does this in some cases. For example,
>>> class d(datetime): pass
...
>>> d.strptime('20080310', '%Y%m%d')
d(2008, 3, 10, 0, 0)
>>> d.now()
d(2008, 3, 10, 20, 27, 6, 303147)
I think date/datetime present a particularly compelling case for
departing from the general rule. These classes are minimal by design
and need to be extended in many applications.
|
|||
| msg107410 - (view) | Author: Alexander Belopolsky (belopolsky) * (Python committer) | Date: 2010年06月09日 18:51 | |
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. |
|||
| msg107414 - (view) | Author: Mark Dickinson (mark.dickinson) * (Python committer) | Date: 2010年06月09日 20:31 | |
If you want to challenge Guido's design decision, I think python-dev would be the place to do it. |
|||
| msg107416 - (view) | Author: Alexander Belopolsky (belopolsky) * (Python committer) | Date: 2010年06月09日 21:03 | |
> If you want to challenge Guido's design decision, I think > python-dev would be the place to do it. Do you have a link supporting that it was "Guido's design decision"? This decision must have been made around class/type unification, but I don't remember reading about it in Guido's essays. I don't want to make a fool of myself by coming to python-dev with this unprepared. :-) |
|||
| msg107417 - (view) | Author: Alexander Belopolsky (belopolsky) * (Python committer) | Date: 2010年06月09日 21:05 | |
I also believe something needs to be fixed here in any case. Either Date.fromordinal(..) should return date or Date(..) + timedelta(..) should return Date. |
|||
| msg107418 - (view) | Author: Mark Dickinson (mark.dickinson) * (Python committer) | Date: 2010年06月09日 21:08 | |
> Do you have a link [...] Nope. Just going on Tim's description of it as "Guido's decision". I've no idea of the history, and I don't particularly recall any recent relevant python-dev discussions. |
|||
| msg108060 - (view) | Author: Brett Cannon (brett.cannon) * (Python committer) | Date: 2010年06月17日 20:30 | |
There is a difference between methods and overridden operators (slightly) in terms of cognitive understanding. I mean creating a new instance from a timestamp seems like an operation on the object by the object. Addition, though, seems like a creation of a new object by the two objects working together, which suggests contravariance. Best I can think of. Otherwise ask on python-dev since Guido called the operator overriding expectation. |
|||
| msg108061 - (view) | Author: Mark Dickinson (mark.dickinson) * (Python committer) | Date: 2010年06月17日 20:52 | |
I had understood that the rule was that alternate constructors should be classmethods, for consistency with __new__. (Well, except that __new__ is actually a staticmethod, of course... )
E.g., after "class MyDecimal(Decimal): pass", MyDecimal('2.3') produces a MyDecimal instance, and by analogy MyDecimal.from_float(2.3) should also produce a MyDecimal instance. It's exactly the same type of function as the class constructor.
I don't think it would do any harm to get clarification from python-dev on the underlying reasons.
|
|||
| msg125979 - (view) | Author: Alexander Belopolsky (belopolsky) * (Python committer) | Date: 2011年01月11日 01:51 | |
Note that before r82065, python prototype, now available as Lib/datetime.py had binary operations implemented to return subclass instances. Here is annotated pre-r82065 code: 39876 gvanrossum def __add__(self, other): 39876 gvanrossum if isinstance(other, timedelta): 39928 gvanrossum return self.__class__(self.__days + other.__days, 39876 gvanrossum self.__seconds + other.__seconds, 39876 gvanrossum self.__microseconds + other.__microseconds) 40207 tim_one return NotImplemented 39876 gvanrossum |
|||
| msg179783 - (view) | Author: Mark Dickinson (mark.dickinson) * (Python committer) | Date: 2013年01月12日 10:15 | |
Alexander: can this be closed as "wont fix"? |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022年04月11日 14:56:31 | admin | set | github: 46520 |
| 2013年01月12日 11:38:19 | belopolsky | set | status: open -> closed resolution: wont fix |
| 2013年01月12日 10:15:33 | mark.dickinson | set | messages: + msg179783 |
| 2013年01月11日 16:20:51 | brett.cannon | set | nosy:
- brett.cannon versions: + Python 3.4, - Python 3.3 |
| 2011年01月11日 01:51:24 | belopolsky | set | nosy:
brett.cannon, amaury.forgeotdarc, mark.dickinson, belopolsky, stingray messages: + msg125979 versions: + Python 3.3, - Python 3.2 |
| 2010年06月17日 20:52:17 | mark.dickinson | set | messages: + msg108061 |
| 2010年06月17日 20:30:54 | brett.cannon | set | nosy:
+ brett.cannon messages: + msg108060 |
| 2010年06月09日 21:08:35 | mark.dickinson | set | messages: + msg107418 |
| 2010年06月09日 21:05:59 | belopolsky | set | messages: + msg107417 |
| 2010年06月09日 21:03:17 | belopolsky | set | messages: + msg107416 |
| 2010年06月09日 20:31:13 | mark.dickinson | set | messages: + msg107414 |
| 2010年06月09日 18:51:06 | belopolsky | set | status: closed -> open assignee: belopolsky components: + Extension Modules, - Library (Lib) versions: + Python 3.2, - Python 2.5 nosy: + mark.dickinson messages: + msg107410 resolution: wont fix -> (no value) |
| 2008年03月11日 00:29:24 | belopolsky | set | messages: + msg63456 |
| 2008年03月10日 23:05:50 | amaury.forgeotdarc | set | status: open -> closed resolution: wont fix messages: + msg63454 nosy: + amaury.forgeotdarc |
| 2008年03月10日 22:21:58 | stingray | set | messages: + msg63453 |
| 2008年03月10日 22:05:22 | belopolsky | set | files:
+ datetime.diff keywords: + patch messages: + msg63452 nosy: + belopolsky |
| 2008年03月10日 19:09:50 | stingray | create | |