I don't think datetime and builtins like int necessarily need to be aligned. But I do see a problem -- the __new__ and __init__ methods defined in the subclass (if any) should allow for being called with the same signature as the base datetime class. Currently you can have a subclass of datetime whose __new__ has no arguments (or, more realistically, interprets its arguments differently). Instances of such a class can still be added to a timedelta. The proposal would cause this to break (since such an addition has to create a new instance, which calls __new__ and __init__). Since this is a backwards incompatibility, I don't see how it can be done -- and I also don't see many use cases, so I think it's not worth pursuing further.
Note that the same problem already happens with the .fromordinal() class method, though it doesn't happen with .fromdatetime() or .now(): >>> class D(datetime.datetime): ... def __new__(cls): return cls.now() ... >>> D() D(2019, 1, 6, 10, 33, 37, 161606) >>> D.fromordinal(100) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: __new__() takes 1 positional argument but 4 were given >>> D.fromtimestamp(123456789) D(1973, 11, 29, 13, 33, 9) >>> On Sun, Jan 6, 2019 at 9:05 AM Paul Ganssle <p...@ganssle.io> wrote: > I can think of many reasons why datetime is different from builtins, > though to be honest I'm not sure that consistency for its own sake is > really a strong argument for keeping a counter-intuitive behavior - and to > be honest I'm open to the idea that *all* arithmetic types *should* have > some form of this change. > > That said, I would say that the biggest difference between datetime and > builtins (other than the fact that datetime is *not* a builtin, and as > such doesn't necessarily need to be categorized in this group), is that > unlike almost all other arithmetic types, *datetime* has a special, > dedicated type for describing differences in datetimes. Using your example > of a float subclass, consider that without the behavior of "addition of > floats returns floats", it would be hard to predict what would happen in > this situation: > > >>> F(1.2) + 3.4 > > Would that always return a float, even though F(1.2) + F(3.4) returns an > F? Would that return an F because F is the left-hand operand? Would it > return a float because float is the right-hand operand? Would you walk the > MROs and find the lowest type in common between the operands and return > that? It's not entirely clear which subtype predominates. With datetime, > you have: > > datetime - datetime -> timedelta > datetime ± timedelta -> datetime > timedelta ± timedelta -> timedelta > > There's no operation between two datetime objects that would return a > datetime object, so it's always clear: operations between datetime > subclasses return timedelta, operations between a datetime object and a > timedelta return the subclass of the datetime that it was added to or > subtracted from. > > Of course, the real way to resolve whether datetime should be different > from int/float/string/etc is to look at why this choice was actually made > for those types in the first place, and decide whether datetime is like > them *in this respect*. The heterogeneous operations problem may be a > reasonable justification for leaving the other builtins alone but changing > datetime, but if someone knows of other fundamental reasons why the > decision to have arithmetic operations always create the base class was > chosen, please let me know. > > Best, > Paul > On 1/5/19 3:55 AM, Alexander Belopolsky wrote: > > > > On Wed, Jan 2, 2019 at 10:18 PM Paul Ganssle <p...@ganssle.io> wrote: > >> .. the original objection was that this implementation assumes that the >> datetime subclass has a constructor with the same (or a sufficiently >> similar) signature as datetime. >> > While this was used as a possible rationale for the way standard types > behave, the main objection to changing datetime classes is that it will > make them behave differently from builtins. For example: > > >>> class F(float): > ... pass > ... > >>> type(F.fromhex('AA')) > <class '__main__.F'> > >>> type(F(1) + F(2)) > <class 'float'> > > This may be a legitimate gripe, but unfortunately that ship has sailed >> long ago. All of datetime's alternate constructors make this assumption. >> Any subclass that does not meet this requirement must have worked around it >> long ago (or they don't care about alternate constructors). >> > > This is right, but the same argument is equally applicable to int, float, > etc. subclasses. If you want to limit your change to datetime types you > should explain what makes these types special. > > _______________________________________________ > Python-Dev mailing list > Python-Dev@python.org > https://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > https://mail.python.org/mailman/options/python-dev/guido%40python.org > -- --Guido van Rossum (python.org/~guido)
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com