I tried porting something from python2 to python3, and was confronted with an error concerning the following class:
class Bound(tuple):
# some methods skipped…
def __new__(cls, value, is_closed):
if value is NegativeInfinity or value is PositiveInfinity:
is_closed = False
return tuple.__new__(cls, (value, is_closed))
def __init__(self, value, is_closed):
"""
See __new__
"""
super(Bound, self).__init__((value, is_closed))
When trying to initialize, it would fail with object.__init__() takes no parameters. It appears that super(Bound, self).__init__(…) accesses the __init__ method of object, which seems wrong – doesn't super just advance at the objects __mro__?
To narrow things down, I wrote the following construction:
class T(tuple):
def __new__(cls, arg):
return super(T, cls).__new__(cls, arg)
def __init__(self, arg):
return super(T, self).__init__(arg)
In this example, I get the same error: T([]) tells me object.__init__() takes no parameters nonetheless.
Since T.__mro__ is (__main__.T, tuple, object), this is inherently confusing. The exact same happens when using super() without explicitly stating type and instance.
What goes wrong?
It appears that
super(Bound, self).__init__(…)accesses the__init__method ofobject, which seems wrong – doesn'tsuperjust advance at the objects__mro__?
object.__init__ is the next __init__ in the MRO, because tuple doesn't have its own __init__.
On Python 2, this would have given you a (suppressed by default) warning. On Python 3, it's an error. You can either remove your __init__ method (which, due to special handling in object.__init__, will stop object.__init__ from complaining), or you can call super(Bound, self).__init__(), without arguments.
For more details, see the explanatory comment in the Python source code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With