int.__init__ incompatible in Python 3.3

Ian Kelly ian.g.kelly at gmail.com
Fri Nov 9 11:30:22 EST 2012


On Fri, Nov 9, 2012 at 4:37 AM, Steven D'Aprano
<steve+comp.lang.python at pearwood.info> wrote:
> In Python 3.3:
>
> py> class X(int):
> ...     def __init__(self, *args):
> ...         super().__init__(*args)  # does nothing, call it anyway
> ...
> py> x = X(22)
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
>   File "<stdin>", line 3, in __init__
> TypeError: object.__init__() takes no parameters
>
>
> It is apparently an oversight, or a bug, that it ever worked in older
> versions.

After reading through the bug history, I think that this change to int
is incorrect, or at least incomplete.  The goal of the change to
object.__init__ is to enable checking for unused arguments when doing
cooperative multiple inheritance, with the idea that each class in the
hierarchy will remove the arguments it uses and pass the rest along.
By the time object.__init__ is reached, any arguments remaining are
unused and extraneous.

In the case of int, int.__new__ takes up to two arguments.  Due to the
nature of the type system, these same two arguments are also passed to
int.__init__.  If each subclass removes its own arguments per the
convention, then by the time int.__init__ is reached, there are still
up to two *expected* arguments remaining.  It should not be the
responsibility of the subclasses (which one? all of them?) to remove
these arguments before calling super().__init__().  The int class
should have the responsibility of accepting and removing these two
arguments *and then* checking that there is nothing left over.

In Python 3.2, int.__init__ happily accepted the int arguments, but
also incorrectly accepted anything else you might pass to it, which
was suboptimal for cooperative multiple inheritance.  In Python 3.3,
it no longer accepts unused arguments, but it also rejects arguments
intended for its own class that it should accept, which as I see it
makes int.__init__ *unusable* for cooperative multiple inheritance.

I realize that the recommendation in the bug comments is to use
__new__ instead of __init__ for subclasses of immutable types.  But
then why have them call __init__ in the first place?  Why even fuss
over what arguments int.__init__ does or does not accept if we're not
supposed to be calling it at all?  And why is that deprecation not
mentioned anywhere in the documentation, that I can find?



More information about the Python-list mailing list