[Python-Dev] subclassing builtin data structures

Alexander Belopolsky alexander.belopolsky at gmail.com
Fri Feb 13 03:39:16 CET 2015


On Thu, Feb 12, 2015 at 7:55 PM, Guido van Rossum <guido at python.org> wrote:

> the problem is that the base class (e.g. int) doesn't know how to
> construct an instance of the subclass -- there is no reason (in general)
> why the signature of a subclass constructor should match the base class
> constructor, and it often doesn't.


I hear this explanation every time we have a discussion about subclassing
of datetime types and I don't really buy this.

Consider this simple subclass:

>>> from datetime import date
>>> class Date(date):
...     pass
...

What do you think Date.today() should return?  Since I did not override
todat() in my Date class, it has to be datetime.date instance, right?

However:

>>> Date.today().__class__
<class '__main__.Date'>

Wait, Date "doesn't know how to construct an instance of the subclass .."

Indeed, if I change the constructor signature, Date.today() won't work:

>>> class Date(date):
...     def __init__(self, extra):
...         pass
...
>>> Date.today()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() takes exactly 2 arguments (4 given)

In my view, a constructor is no different from any other method.  If the
designers of the subclass decided to change the signature in an
incompatible way, they should either override all methods that create new
objects or live with tracebacks.

On the other hand, if all I want in my Date class is a better __format__
method, I am forced to override all operators or have my objects silently
degrade in situations like this:

>>> d = Date.today()
>>> d.__class__
<class '__main__.Date'>
>>> d += timedelta(1)
>>> d.__class__
<type 'datetime.date'>

Having binary operations return subclass instances is not without
precedent.  For example, in numpy,

>>> from numpy import ndarray
>>> class Array(ndarray):
...     pass
...
>>> a = Array(1)
>>> a[0] = 42
>>> a
Array([ 42.])
>>> a + a
Array([ 84.])

I believe numpy had this behavior since types became subclassable in
Python, so this design is definitely not a "no-go."
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20150212/e93a86a0/attachment.html>


More information about the Python-Dev mailing list